From 06cfcd57fc8093107a871984c4f9105fa9fff227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 4 Oct 2019 09:11:30 +0300 Subject: [PATCH] Move to_string() methods into the Display trait or rename to to_str(), move from_string() into the FromStr trait Fixes clippy warnings, prevents confusing errors and is more consistent. The Display trait provides a to_string() method by itself and FromStr provides from_str(). --- examples/src/bin/appsink.rs | 2 +- examples/src/bin/glupload.rs | 2 +- examples/src/bin/pad_probes.rs | 2 +- gstreamer-audio/src/audio_format.rs | 32 +++--- gstreamer-video/src/video_format.rs | 31 +++--- gstreamer-video/src/video_info.rs | 105 ++++++++---------- gstreamer-video/src/video_time_code.rs | 34 +++--- .../src/video_time_code_interval.rs | 24 ++-- gstreamer/src/caps.rs | 22 ++-- gstreamer/src/caps_features.rs | 38 +++---- gstreamer/src/structure.rs | 41 +++---- gstreamer/src/tags.rs | 13 ++- 12 files changed, 154 insertions(+), 192 deletions(-) diff --git a/examples/src/bin/appsink.rs b/examples/src/bin/appsink.rs index 26c321fe9..eb30de291 100644 --- a/examples/src/bin/appsink.rs +++ b/examples/src/bin/appsink.rs @@ -73,7 +73,7 @@ fn create_pipeline() -> Result { appsink.set_caps(Some(&gst::Caps::new_simple( "audio/x-raw", &[ - ("format", &gst_audio::AUDIO_FORMAT_S16.to_string()), + ("format", &gst_audio::AUDIO_FORMAT_S16.to_str()), ("layout", &"interleaved"), ("channels", &(1i32)), ("rate", &gst::IntRange::::new(1, i32::MAX)), diff --git a/examples/src/bin/glupload.rs b/examples/src/bin/glupload.rs index a1ffac870..ceb4ba5d4 100644 --- a/examples/src/bin/glupload.rs +++ b/examples/src/bin/glupload.rs @@ -559,7 +559,7 @@ impl App { let caps = gst::Caps::builder("video/x-raw") .features(&[&gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY]) - .field("format", &gst_video::VideoFormat::Rgba.to_string()) + .field("format", &gst_video::VideoFormat::Rgba.to_str()) .field("texture-target", &"2D") .build(); appsink.set_caps(Some(&caps)); diff --git a/examples/src/bin/pad_probes.rs b/examples/src/bin/pad_probes.rs index ec3d0fb45..9b5af8f8d 100644 --- a/examples/src/bin/pad_probes.rs +++ b/examples/src/bin/pad_probes.rs @@ -27,7 +27,7 @@ fn example_main() { // from the resulting pipeline. let pipeline = gst::parse_launch(&format!( "audiotestsrc name=src ! audio/x-raw,format={},channels=1 ! fakesink", - gst_audio::AUDIO_FORMAT_S16.to_string() + gst_audio::AUDIO_FORMAT_S16.to_str() )) .unwrap(); let pipeline = pipeline.dynamic_cast::().unwrap(); diff --git a/gstreamer-audio/src/audio_format.rs b/gstreamer-audio/src/audio_format.rs index ce5fe4809..932506bd4 100644 --- a/gstreamer-audio/src/audio_format.rs +++ b/gstreamer-audio/src/audio_format.rs @@ -12,7 +12,7 @@ use std::ffi::CStr; use std::fmt; use std::str; -use glib::translate::{from_glib, ToGlib, ToGlibPtr}; +use glib::translate::{from_glib, FromGlib, ToGlib, ToGlibPtr}; impl ::AudioFormat { pub fn build_integer( @@ -33,17 +33,7 @@ impl ::AudioFormat { } } - pub fn from_string(s: &str) -> ::AudioFormat { - assert_initialized_main_thread!(); - - unsafe { - from_glib(gst_audio_sys::gst_audio_format_from_string( - s.to_glib_none().0, - )) - } - } - - pub fn to_string<'a>(self) -> &'a str { + pub fn to_str<'a>(self) -> &'a str { if self == ::AudioFormat::Unknown { return "UNKNOWN"; } @@ -60,20 +50,24 @@ impl str::FromStr for ::AudioFormat { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); + assert_initialized_main_thread!(); - let format = Self::from_string(s); - if format == ::AudioFormat::Unknown { - Err(()) - } else { - Ok(format) + unsafe { + let fmt = ::AudioFormat::from_glib(gst_audio_sys::gst_audio_format_from_string( + s.to_glib_none().0, + )); + if fmt == ::AudioFormat::Unknown { + Err(()) + } else { + Ok(fmt) + } } } } impl fmt::Display for ::AudioFormat { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(::AudioFormat::to_string(*self)) + f.write_str((*self).to_str()) } } diff --git a/gstreamer-video/src/video_format.rs b/gstreamer-video/src/video_format.rs index 5ee6113cc..e59bcc4a1 100644 --- a/gstreamer-video/src/video_format.rs +++ b/gstreamer-video/src/video_format.rs @@ -46,16 +46,6 @@ impl ToGlib for VideoEndianness { } impl ::VideoFormat { - pub fn from_string(s: &str) -> ::VideoFormat { - assert_initialized_main_thread!(); - - unsafe { - from_glib(gst_video_sys::gst_video_format_from_string( - s.to_glib_none().0, - )) - } - } - pub fn from_fourcc(fourcc: u32) -> ::VideoFormat { assert_initialized_main_thread!(); @@ -86,7 +76,7 @@ impl ::VideoFormat { } } - pub fn to_string<'a>(self) -> &'a str { + pub fn to_str<'a>(self) -> &'a str { if self == ::VideoFormat::Unknown { return "UNKNOWN"; } @@ -103,20 +93,25 @@ impl str::FromStr for ::VideoFormat { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); + assert_initialized_main_thread!(); - let format = Self::from_string(s); - if format == ::VideoFormat::Unknown { - Err(()) - } else { - Ok(format) + unsafe { + let fmt = ::VideoFormat::from_glib(gst_video_sys::gst_video_format_from_string( + s.to_glib_none().0, + )); + + if fmt == ::VideoFormat::Unknown { + Err(()) + } else { + Ok(fmt) + } } } } impl fmt::Display for ::VideoFormat { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(::VideoFormat::to_string(*self)) + f.write_str((*self).to_str()) } } diff --git a/gstreamer-video/src/video_info.rs b/gstreamer-video/src/video_info.rs index c2bef456a..218fdba88 100644 --- a/gstreamer-video/src/video_info.rs +++ b/gstreamer-video/src/video_info.rs @@ -12,12 +12,13 @@ use gst_video_sys; use glib; use glib::translate::{ - from_glib, from_glib_full, from_glib_none, FromGlib, FromGlibPtrNone, ToGlib, ToGlibPtr, - ToGlibPtrMut, + from_glib, from_glib_full, from_glib_none, FromGlib, FromGlibPtrFull, FromGlibPtrNone, ToGlib, + ToGlibPtr, ToGlibPtrMut, }; use gst; use gst::prelude::*; +use std::ffi::CStr; use std::fmt; use std::mem; use std::ptr; @@ -110,27 +111,6 @@ impl VideoColorimetry { VideoColorimetry(colorimetry) } - pub fn to_string(&self) -> String { - unsafe { from_glib_full(gst_video_sys::gst_video_colorimetry_to_string(&self.0)) } - } - - pub fn from_string(s: &str) -> Option { - assert_initialized_main_thread!(); - - unsafe { - let mut colorimetry = mem::MaybeUninit::zeroed(); - let valid: bool = from_glib(gst_video_sys::gst_video_colorimetry_from_string( - colorimetry.as_mut_ptr(), - s.to_glib_none().0, - )); - if valid { - Some(VideoColorimetry(colorimetry.assume_init())) - } else { - None - } - } - } - pub fn range(&self) -> ::VideoColorRange { from_glib(self.0.range) } @@ -170,8 +150,20 @@ impl str::FromStr for ::VideoColorimetry { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Self::from_string(s).ok_or(()) + assert_initialized_main_thread!(); + + unsafe { + let mut colorimetry = mem::MaybeUninit::zeroed(); + let valid: bool = from_glib(gst_video_sys::gst_video_colorimetry_from_string( + colorimetry.as_mut_ptr(), + s.to_glib_none().0, + )); + if valid { + Ok(VideoColorimetry(colorimetry.assume_init())) + } else { + Err(()) + } + } } } @@ -188,7 +180,10 @@ impl fmt::Debug for ::VideoColorimetry { impl fmt::Display for ::VideoColorimetry { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(&::VideoColorimetry::to_string(self)) + let s = unsafe { + glib::GString::from_glib_full(gst_video_sys::gst_video_colorimetry_to_string(&self.0)) + }; + f.write_str(&s) } } @@ -822,21 +817,13 @@ impl glib::translate::FromGlibPtrFull<*mut gst_video_sys::GstVideoInfo> for Vide #[cfg(any(feature = "v1_12", feature = "dox"))] impl ::VideoFieldOrder { - pub fn to_string(self) -> String { + pub fn to_str<'a>(self) -> &'a str { unsafe { - from_glib_none(gst_video_sys::gst_video_field_order_to_string( + CStr::from_ptr(gst_video_sys::gst_video_field_order_to_string( self.to_glib(), )) - } - } - - pub fn from_string(s: &str) -> Self { - assert_initialized_main_thread!(); - - unsafe { - from_glib(gst_video_sys::gst_video_field_order_from_string( - s.to_glib_none().0, - )) + .to_str() + .unwrap() } } } @@ -846,34 +833,31 @@ impl str::FromStr for ::VideoFieldOrder { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Ok(Self::from_string(s)) + assert_initialized_main_thread!(); + + unsafe { + Ok(from_glib(gst_video_sys::gst_video_field_order_from_string( + s.to_glib_none().0, + ))) + } } } #[cfg(any(feature = "v1_12", feature = "dox"))] impl fmt::Display for ::VideoFieldOrder { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(&::VideoFieldOrder::to_string(*self)) + f.write_str((*self).to_str()) } } impl ::VideoInterlaceMode { - pub fn to_string(self) -> String { + pub fn to_str<'a>(self) -> &'a str { unsafe { - from_glib_none(gst_video_sys::gst_video_interlace_mode_to_string( + CStr::from_ptr(gst_video_sys::gst_video_interlace_mode_to_string( self.to_glib(), )) - } - } - - pub fn from_string(s: &str) -> Self { - assert_initialized_main_thread!(); - - unsafe { - from_glib(gst_video_sys::gst_video_interlace_mode_from_string( - s.to_glib_none().0, - )) + .to_str() + .unwrap() } } } @@ -882,14 +866,19 @@ impl str::FromStr for ::VideoInterlaceMode { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Ok(Self::from_string(s)) + assert_initialized_main_thread!(); + + unsafe { + Ok(from_glib( + gst_video_sys::gst_video_interlace_mode_from_string(s.to_glib_none().0), + )) + } } } impl fmt::Display for ::VideoInterlaceMode { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(&::VideoInterlaceMode::to_string(*self)) + f.write_str((*self).to_str()) } } @@ -992,9 +981,11 @@ mod tests { #[cfg(any(feature = "v1_12", feature = "dox"))] #[test] fn test_display() { + use std::str::FromStr; + gst::init().unwrap(); - format!("{}", ::VideoColorimetry::from_string("sRGB").unwrap()); + format!("{}", ::VideoColorimetry::from_str("sRGB").unwrap()); format!("{}", ::VideoFieldOrder::TopFieldFirst); format!("{}", ::VideoInterlaceMode::Progressive); } diff --git a/gstreamer-video/src/video_time_code.rs b/gstreamer-video/src/video_time_code.rs index 79cd45fff..70b6c81de 100644 --- a/gstreamer-video/src/video_time_code.rs +++ b/gstreamer-video/src/video_time_code.rs @@ -99,16 +99,6 @@ impl VideoTimeCode { } } - #[cfg(any(feature = "v1_12", feature = "dox"))] - pub fn from_string(tc_str: &str) -> Option { - assert_initialized_main_thread!(); - unsafe { - from_glib_full(gst_video_sys::gst_video_time_code_new_from_string( - tc_str.to_glib_none().0, - )) - } - } - pub fn is_valid(&self) -> bool { unsafe { from_glib(gst_video_sys::gst_video_time_code_is_valid( @@ -246,14 +236,6 @@ impl ValidVideoTimeCode { macro_rules! generic_impl { ($name:ident) => { impl $name { - pub fn to_string(&self) -> String { - unsafe { - from_glib_full(gst_video_sys::gst_video_time_code_to_string( - self.to_glib_none().0, - )) - } - } - pub fn get_hours(&self) -> u32 { self.0.hours } @@ -338,7 +320,12 @@ macro_rules! generic_impl { impl fmt::Display for $name { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + let s = unsafe { + glib::GString::from_glib_full(gst_video_sys::gst_video_time_code_to_string( + self.to_glib_none().0, + )) + }; + f.write_str(&s) } } @@ -482,8 +469,13 @@ impl str::FromStr for VideoTimeCode { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Self::from_string(s).ok_or(()) + assert_initialized_main_thread!(); + unsafe { + Option::::from_glib_full( + gst_video_sys::gst_video_time_code_new_from_string(s.to_glib_none().0), + ) + .ok_or(()) + } } } diff --git a/gstreamer-video/src/video_time_code_interval.rs b/gstreamer-video/src/video_time_code_interval.rs index 1d174bbf6..1e2f28447 100644 --- a/gstreamer-video/src/video_time_code_interval.rs +++ b/gstreamer-video/src/video_time_code_interval.rs @@ -17,20 +17,12 @@ use std::cmp; use std::fmt; use std::mem; use std::ptr; +use std::str; #[derive(Clone)] pub struct VideoTimeCodeInterval(gst_video_sys::GstVideoTimeCodeInterval); impl VideoTimeCodeInterval { - pub fn from_string(tc_inter_str: &str) -> Option { - assert_initialized_main_thread!(); - unsafe { - from_glib_full(gst_video_sys::gst_video_time_code_interval_new_from_string( - tc_inter_str.to_glib_none().0, - )) - } - } - pub fn new(hours: u32, minutes: u32, seconds: u32, frames: u32) -> Self { assert_initialized_main_thread!(); unsafe { @@ -135,6 +127,20 @@ impl fmt::Display for VideoTimeCodeInterval { } } +impl str::FromStr for VideoTimeCodeInterval { + type Err = (); + + fn from_str(s: &str) -> Result { + assert_initialized_main_thread!(); + unsafe { + Option::::from_glib_full( + gst_video_sys::gst_video_time_code_interval_new_from_string(s.to_glib_none().0), + ) + .ok_or(()) + } + } +} + #[doc(hidden)] impl GlibPtrDefault for VideoTimeCodeInterval { type GlibType = *mut gst_video_sys::GstVideoTimeCodeInterval; diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index 9fb114aaa..8da4bae8a 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -16,7 +16,7 @@ use structure::*; use CapsIntersectMode; use glib; -use glib::translate::{from_glib, from_glib_full, ToGlib, ToGlibPtr}; +use glib::translate::{from_glib, from_glib_full, FromGlibPtrFull, ToGlib, ToGlibPtr}; use glib::value::ToSendValue; use gst_sys; @@ -54,11 +54,6 @@ impl Caps { caps } - pub fn from_string(value: &str) -> Option { - assert_initialized_main_thread!(); - unsafe { from_glib_full(gst_sys::gst_caps_from_string(value.to_glib_none().0)) } - } - pub fn fixate(caps: Self) -> Self { skip_assert_initialized!(); unsafe { from_glib_full(gst_sys::gst_caps_fixate(caps.into_ptr())) } @@ -114,8 +109,11 @@ impl str::FromStr for Caps { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Caps::from_string(s).ok_or(()) + assert_initialized_main_thread!(); + unsafe { + Option::::from_glib_full(gst_sys::gst_caps_from_string(s.to_glib_none().0)) + .ok_or(()) + } } } @@ -140,10 +138,6 @@ impl CapsRef { } } - pub fn to_string(&self) -> String { - unsafe { from_glib_full(gst_sys::gst_caps_to_string(self.as_ptr())) } - } - pub fn get_structure(&self, idx: u32) -> Option<&StructureRef> { if idx >= self.get_size() { return None; @@ -509,7 +503,9 @@ impl fmt::Debug for CapsRef { impl fmt::Display for CapsRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&CapsRef::to_string(self)) + let s = + unsafe { glib::GString::from_glib_full(gst_sys::gst_caps_to_string(self.as_ptr())) }; + f.write_str(&s) } } diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index 77da06871..00c0c1e70 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -63,21 +63,6 @@ impl CapsFeatures { } } - pub fn from_string(value: &str) -> Option { - assert_initialized_main_thread!(); - unsafe { - let ptr = gst_sys::gst_caps_features_from_string(value.to_glib_none().0); - if ptr.is_null() { - return None; - } - - Some(CapsFeatures( - ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef), - PhantomData, - )) - } - } - pub unsafe fn into_ptr(self) -> *mut gst_sys::GstCapsFeatures { let ptr = self.0.as_ptr() as *mut CapsFeaturesRef as *mut gst_sys::GstCapsFeatures; mem::forget(self); @@ -148,8 +133,18 @@ impl str::FromStr for CapsFeatures { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - CapsFeatures::from_string(s).ok_or(()) + assert_initialized_main_thread!(); + unsafe { + let ptr = gst_sys::gst_caps_features_from_string(s.to_glib_none().0); + if ptr.is_null() { + return Err(()); + } + + Ok(CapsFeatures( + ptr::NonNull::new_unchecked(ptr as *mut CapsFeaturesRef), + PhantomData, + )) + } } } @@ -302,10 +297,6 @@ impl CapsFeaturesRef { self as *const Self as *mut gst_sys::GstCapsFeatures } - pub fn to_string(&self) -> String { - unsafe { from_glib_full(gst_sys::gst_caps_features_to_string(self.as_ptr())) } - } - pub fn is_empty(&self) -> bool { self.get_size() == 0 && !self.is_any() } @@ -448,7 +439,10 @@ impl fmt::Debug for CapsFeaturesRef { impl fmt::Display for CapsFeaturesRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.to_string()) + let s = unsafe { + glib::GString::from_glib_full(gst_sys::gst_caps_features_to_string(self.as_ptr())) + }; + f.write_str(&s) } } diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index c435e5077..e0f75e92e 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -109,21 +109,6 @@ impl Structure { structure } - pub fn from_string(s: &str) -> Option { - assert_initialized_main_thread!(); - unsafe { - let structure = gst_sys::gst_structure_from_string(s.to_glib_none().0, ptr::null_mut()); - if structure.is_null() { - None - } else { - Some(Structure( - ptr::NonNull::new_unchecked(structure as *mut StructureRef), - PhantomData, - )) - } - } - } - pub unsafe fn into_ptr(self) -> *mut gst_sys::GstStructure { let ptr = self.0.as_ptr() as *mut StructureRef as *mut gst_sys::GstStructure; mem::forget(self); @@ -206,8 +191,18 @@ impl str::FromStr for Structure { type Err = (); fn from_str(s: &str) -> Result { - skip_assert_initialized!(); - Structure::from_string(s).ok_or(()) + assert_initialized_main_thread!(); + unsafe { + let structure = gst_sys::gst_structure_from_string(s.to_glib_none().0, ptr::null_mut()); + if structure.is_null() { + Err(()) + } else { + Ok(Structure( + ptr::NonNull::new_unchecked(structure as *mut StructureRef), + PhantomData, + )) + } + } } } @@ -373,10 +368,6 @@ impl StructureRef { self as *const Self as *mut gst_sys::GstStructure } - pub fn to_string(&self) -> String { - unsafe { from_glib_full(gst_sys::gst_structure_to_string(&self.0)) } - } - pub fn get<'structure, 'name, T: FromValueOptional<'structure>>( &'structure self, name: &'name str, @@ -598,7 +589,8 @@ impl StructureRef { impl fmt::Display for StructureRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.to_string()) + let s = unsafe { glib::GString::from_glib_full(gst_sys::gst_structure_to_string(&self.0)) }; + f.write_str(&s) } } @@ -749,6 +741,7 @@ impl Builder { #[cfg(test)] mod tests { use super::*; + use std::str::FromStr; #[test] fn new_set_get() { @@ -831,7 +824,7 @@ mod tests { let a = "Test, f1=(string)abc, f2=(uint)123;"; - let s = Structure::from_string(&a).unwrap(); + let s = Structure::from_str(&a).unwrap(); assert_eq!(s.get::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s.get_some::("f2"), Ok(123)); @@ -844,7 +837,7 @@ mod tests { let a = glib::value::Value::from(None::<&Structure>); assert!(a.get::().unwrap().is_none()); - let b = glib::value::Value::from(&Structure::from_string(&"foo").unwrap()); + let b = glib::value::Value::from(&Structure::from_str(&"foo").unwrap()); assert!(b.get::().unwrap().is_some()); } } diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 644dcba1f..03cfde1ca 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -12,7 +12,9 @@ use std::marker::PhantomData; use std::mem; use glib; -use glib::translate::{from_glib, from_glib_full, ToGlib, ToGlibPtr, ToGlibPtrMut}; +use glib::translate::{ + from_glib, from_glib_full, FromGlibPtrFull, ToGlib, ToGlibPtr, ToGlibPtrMut, +}; use glib::value::{FromValueOptional, SendValue, SetValue, ToSendValue, TypedValue, Value}; use glib::StaticType; use gobject_sys; @@ -488,10 +490,6 @@ impl TagListRef { Iter::new(self) } - pub fn to_string(&self) -> String { - unsafe { from_glib_full(gst_sys::gst_tag_list_to_string(self.as_ptr())) } - } - pub fn insert(&mut self, other: &TagListRef, mode: TagMergeMode) { unsafe { gst_sys::gst_tag_list_insert(self.as_mut_ptr(), other.as_ptr(), mode.to_glib()) } } @@ -523,7 +521,10 @@ impl fmt::Debug for TagListRef { impl fmt::Display for TagListRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&TagListRef::to_string(self)) + let s = unsafe { + glib::GString::from_glib_full(gst_sys::gst_tag_list_to_string(self.as_ptr())) + }; + f.write_str(&s) } }