reformat code again

This commit is contained in:
Quentin 2023-07-24 12:37:30 +02:00
parent 5cfa06dbf8
commit d42062ce48
Signed by: quentin
GPG key ID: E9602264D639FF68
18 changed files with 194 additions and 131 deletions

View file

@ -1,5 +1,3 @@
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum EMLError<'a> { pub enum EMLError<'a> {
ParseError(nom::Err<nom::error::Error<&'a [u8]>>), ParseError(nom::Err<nom::error::Error<&'a [u8]>>),

View file

@ -176,8 +176,8 @@ mod tests {
); );
} }
use crate::text::encoding::{EncodedWord, QuotedChunk, QuotedWord};
use crate::text::quoted::QuotedString; use crate::text::quoted::QuotedString;
use crate::text::encoding::{EncodedWord, QuotedWord, QuotedChunk};
#[test] #[test]
fn test_strange_groups() { fn test_strange_groups() {
@ -186,20 +186,24 @@ mod tests {
br#""Colleagues": "James Smythe" <james@vandelay.com>;, Friends: br#""Colleagues": "James Smythe" <james@vandelay.com>;, Friends:
jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= <john@example.com>;"# jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= <john@example.com>;"#
), ),
Ok((&b""[..], vec![ Ok((
&b""[..],
vec![
AddressRef::Many(GroupRef { AddressRef::Many(GroupRef {
name: Phrase(vec![Word::Quoted(QuotedString(vec![&b"Colleagues"[..]]))]), name: Phrase(vec![Word::Quoted(QuotedString(vec![&b"Colleagues"[..]]))]),
participants: vec![ participants: vec![MailboxRef {
MailboxRef {
name: Some(Phrase(vec![Word::Quoted(QuotedString(vec![ name: Some(Phrase(vec![Word::Quoted(QuotedString(vec![
&b"James"[..], &b" "[..], &b"Smythe"[..] &b"James"[..],
&b" "[..],
&b"Smythe"[..]
]))])), ]))])),
addrspec: AddrSpec { addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"james"[..]))]), local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(
&b"james"[..]
))]),
domain: Domain::Atoms(vec![&b"vandelay"[..], &b"com"[..]]), domain: Domain::Atoms(vec![&b"vandelay"[..], &b"com"[..]]),
} }
}, },],
],
}), }),
AddressRef::Many(GroupRef { AddressRef::Many(GroupRef {
name: Phrase(vec![Word::Atom(&b"Friends"[..])]), name: Phrase(vec![Word::Atom(&b"Friends"[..])]),
@ -207,12 +211,15 @@ mod tests {
MailboxRef { MailboxRef {
name: None, name: None,
addrspec: AddrSpec { addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"jane"[..]))]), local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(
&b"jane"[..]
))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]), domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
} }
}, },
MailboxRef { MailboxRef {
name: Some(Phrase(vec![Word::Encoded(EncodedWord::Quoted(QuotedWord { name: Some(Phrase(vec![Word::Encoded(EncodedWord::Quoted(
QuotedWord {
enc: encoding_rs::UTF_8, enc: encoding_rs::UTF_8,
chunks: vec![ chunks: vec![
QuotedChunk::Safe(&b"John"[..]), QuotedChunk::Safe(&b"John"[..]),
@ -221,15 +228,19 @@ mod tests {
QuotedChunk::Encoded(vec![0xc3, 0xae]), QuotedChunk::Encoded(vec![0xc3, 0xae]),
QuotedChunk::Safe(&b"th"[..]), QuotedChunk::Safe(&b"th"[..]),
] ]
}))])), }
))])),
addrspec: AddrSpec { addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"john"[..]))]), local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(
&b"john"[..]
))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]), domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
} }
}, },
] ]
}), }),
])) ]
))
); );
} }
} }

View file

@ -11,9 +11,9 @@ use crate::imf::address::{address_list, mailbox_list, nullable_address_list, Add
use crate::imf::datetime::section as date; use crate::imf::datetime::section as date;
use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList}; use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList};
use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef}; use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef};
use crate::imf::Imf;
use crate::imf::mime::{version, Version}; use crate::imf::mime::{version, Version};
use crate::imf::trace::{received_log, return_path, ReceivedLog}; use crate::imf::trace::{received_log, return_path, ReceivedLog};
use crate::imf::Imf;
use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured}; use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured};
use crate::text::whitespace::obs_crlf; use crate::text::whitespace::obs_crlf;

View file

@ -1,4 +1,3 @@
use std::fmt;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, take_while}, bytes::complete::{tag, take_while},
@ -7,6 +6,7 @@ use nom::{
sequence::{delimited, pair, tuple}, sequence::{delimited, pair, tuple},
IResult, IResult,
}; };
use std::fmt;
use crate::imf::mailbox::is_dtext; use crate::imf::mailbox::is_dtext;
use crate::text::whitespace::cfws; use crate::text::whitespace::cfws;
@ -19,17 +19,22 @@ pub struct MessageID<'a> {
} }
impl<'a> ToString for MessageID<'a> { impl<'a> ToString for MessageID<'a> {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!("{}@{}", String::from_utf8_lossy(self.left), String::from_utf8_lossy(self.right)) format!(
"{}@{}",
String::from_utf8_lossy(self.left),
String::from_utf8_lossy(self.right)
)
} }
} }
impl<'a> fmt::Debug for MessageID<'a> { impl<'a> fmt::Debug for MessageID<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("MessageID").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("MessageID")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }
pub type MessageIDList<'a> = Vec<MessageID<'a>>; pub type MessageIDList<'a> = Vec<MessageID<'a>>;
/// Message identifier /// Message identifier
/// ///
/// ```abnf /// ```abnf

View file

@ -1,4 +1,3 @@
use std::fmt;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, take_while1}, bytes::complete::{tag, take_while1},
@ -7,6 +6,7 @@ use nom::{
sequence::{delimited, pair, preceded, terminated, tuple}, sequence::{delimited, pair, preceded, terminated, tuple},
IResult, IResult,
}; };
use std::fmt;
use crate::text::ascii; use crate::text::ascii;
use crate::text::misc_token::{phrase, word, Phrase, Word}; use crate::text::misc_token::{phrase, word, Phrase, Word};
@ -29,7 +29,9 @@ impl<'a> ToString for AddrSpec<'a> {
} }
impl<'a> fmt::Debug for AddrSpec<'a> { impl<'a> fmt::Debug for AddrSpec<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("AddrSpec").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("AddrSpec")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }
@ -209,7 +211,9 @@ impl<'a> ToString for Domain<'a> {
} }
impl<'a> fmt::Debug for Domain<'a> { impl<'a> fmt::Debug for Domain<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("Domain").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("Domain")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }

View file

@ -53,8 +53,7 @@ pub struct Imf<'a> {
// it may result in missing data or silently overriden data. // it may result in missing data or silently overriden data.
impl<'a> FromIterator<Field<'a>> for Imf<'a> { impl<'a> FromIterator<Field<'a>> for Imf<'a> {
fn from_iter<I: IntoIterator<Item = Field<'a>>>(iter: I) -> Self { fn from_iter<I: IntoIterator<Item = Field<'a>>>(iter: I) -> Self {
iter.into_iter() iter.into_iter().fold(Imf::default(), |mut section, field| {
.fold(Imf::default(), |mut section, field| {
match field { match field {
Field::Date(v) => section.date = v, Field::Date(v) => section.date = v,
Field::From(v) => section.from.extend(v), Field::From(v) => section.from.extend(v),

View file

@ -1,8 +1,8 @@
mod error; mod error;
mod header; mod header;
mod imf;
mod mime; mod mime;
mod part; mod part;
mod imf;
mod text; mod text;
pub fn email(input: &[u8]) -> Result<part::composite::Message, error::EMLError> { pub fn email(input: &[u8]) -> Result<part::composite::Message, error::EMLError> {

View file

@ -6,10 +6,10 @@ use nom::{
}; };
use crate::header::{field_name, CompFieldList}; use crate::header::{field_name, CompFieldList};
use crate::imf::identification::{msg_id, MessageID};
use crate::mime::mechanism::{mechanism, Mechanism}; use crate::mime::mechanism::{mechanism, Mechanism};
use crate::mime::mime::AnyMIME; use crate::mime::mime::AnyMIME;
use crate::mime::r#type::{naive_type, NaiveType}; use crate::mime::r#type::{naive_type, NaiveType};
use crate::imf::identification::{msg_id, MessageID};
use crate::text::misc_token::{unstructured, Unstructured}; use crate::text::misc_token::{unstructured, Unstructured};
use crate::text::whitespace::obs_crlf; use crate::text::whitespace::obs_crlf;

View file

@ -1,7 +1,7 @@
use crate::imf::identification::MessageID;
use crate::mime::field::Content; use crate::mime::field::Content;
use crate::mime::mechanism::Mechanism; use crate::mime::mechanism::Mechanism;
use crate::mime::r#type::{self as ctype, AnyType}; use crate::mime::r#type::{self as ctype, AnyType};
use crate::imf::identification::MessageID;
use crate::text::misc_token::Unstructured; //Multipart, Message, Text, Binary}; use crate::text::misc_token::Unstructured; //Multipart, Message, Text, Binary};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]

View file

@ -1,5 +1,5 @@
use nom::{ use nom::{
bytes::complete::{tag}, bytes::complete::tag,
combinator::{map, opt}, combinator::{map, opt},
multi::many0, multi::many0,
sequence::{preceded, terminated, tuple}, sequence::{preceded, terminated, tuple},
@ -260,14 +260,10 @@ mod tests {
parameter_list(b";boundary=\"festivus\";"), parameter_list(b";boundary=\"festivus\";"),
Ok(( Ok((
&b""[..], &b""[..],
vec![ vec![Parameter {
Parameter {
name: &b"boundary"[..], name: &b"boundary"[..],
value: MIMEWord::Quoted(QuotedString(vec![ value: MIMEWord::Quoted(QuotedString(vec![&b"festivus"[..]])),
&b"festivus"[..] }],
])),
}
],
)) ))
); );
} }

View file

@ -1,16 +1,16 @@
use nom::IResult; use nom::IResult;
use crate::header::{header, CompFieldList}; use crate::header::{header, CompFieldList};
use crate::mime;
use crate::imf::{self as imf}; use crate::imf::{self as imf};
use crate::mime;
use crate::part::{self, AnyPart};
use crate::text::boundary::{boundary, Delimiter}; use crate::text::boundary::{boundary, Delimiter};
use crate::part::{AnyPart, self};
//--- Multipart //--- Multipart
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Multipart<'a> { pub struct Multipart<'a> {
pub interpreted: mime::mime::Multipart<'a>, pub interpreted: mime::mime::Multipart<'a>,
pub children: Vec<AnyPart<'a>> pub children: Vec<AnyPart<'a>>,
} }
pub fn multipart<'a>( pub fn multipart<'a>(
@ -24,8 +24,24 @@ pub fn multipart<'a>(
let mut mparts: Vec<AnyPart> = vec![]; let mut mparts: Vec<AnyPart> = vec![];
loop { loop {
let input = match boundary(bound)(input_loop) { let input = match boundary(bound)(input_loop) {
Err(_) => return Ok((input_loop, Multipart { interpreted: m.clone(), children: mparts })), Err(_) => {
Ok((inp, Delimiter::Last)) => return Ok((inp, Multipart{ interpreted: m.clone(), children: mparts})), return Ok((
input_loop,
Multipart {
interpreted: m.clone(),
children: mparts,
},
))
}
Ok((inp, Delimiter::Last)) => {
return Ok((
inp,
Multipart {
interpreted: m.clone(),
children: mparts,
},
))
}
Ok((inp, Delimiter::Next)) => inp, Ok((inp, Delimiter::Next)) => inp,
}; };
@ -57,25 +73,32 @@ pub fn message<'a>(
m: mime::mime::Message<'a>, m: mime::mime::Message<'a>,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Message<'a>> { ) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Message<'a>> {
move |input: &[u8]| { move |input: &[u8]| {
let (input, fields): (_, CompFieldList<part::field::MixedField>) = header(part::field::mixed_field)(input)?; let (input, fields): (_, CompFieldList<part::field::MixedField>) =
header(part::field::mixed_field)(input)?;
let (in_mime, imf) = fields.sections(); let (in_mime, imf) = fields.sections();
let part = part::to_anypart(in_mime, input); let part = part::to_anypart(in_mime, input);
Ok((&[], Message { interpreted: m.clone(), imf, child: Box::new(part) })) Ok((
&[],
Message {
interpreted: m.clone(),
imf,
child: Box::new(part),
},
))
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::text::encoding::{Base64Word, EncodedWord, QuotedChunk, QuotedWord};
use crate::text::misc_token::{Phrase, UnstrToken, Unstructured, Word};
use crate::part::discrete::Text; use crate::part::discrete::Text;
use crate::part::AnyPart; use crate::part::AnyPart;
use crate::text::encoding::{Base64Word, EncodedWord, QuotedChunk, QuotedWord};
use crate::text::misc_token::{Phrase, UnstrToken, Unstructured, Word};
use chrono::{FixedOffset, TimeZone}; use chrono::{FixedOffset, TimeZone};
#[test] #[test]
fn test_multipart() { fn test_multipart() {
let base_mime = mime::mime::Multipart( let base_mime = mime::mime::Multipart(

View file

@ -5,15 +5,17 @@ use crate::mime;
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Text<'a> { pub struct Text<'a> {
pub interpreted: mime::mime::Text<'a>, pub interpreted: mime::mime::Text<'a>,
pub body: &'a [u8] pub body: &'a [u8],
} }
impl<'a> fmt::Debug for Text<'a> { impl<'a> fmt::Debug for Text<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt fmt.debug_struct("part::Text")
.debug_struct("part::Text")
.field("mime", &self.interpreted) .field("mime", &self.interpreted)
.field("body", &format_args!("\"{}\"", String::from_utf8_lossy(self.body))) .field(
"body",
&format_args!("\"{}\"", String::from_utf8_lossy(self.body)),
)
.finish() .finish()
} }
} }
@ -21,15 +23,17 @@ impl<'a> fmt::Debug for Text<'a> {
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Binary<'a> { pub struct Binary<'a> {
pub interpreted: mime::mime::Binary<'a>, pub interpreted: mime::mime::Binary<'a>,
pub body: &'a [u8] pub body: &'a [u8],
} }
impl<'a> fmt::Debug for Binary<'a> { impl<'a> fmt::Debug for Binary<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt fmt.debug_struct("part::Binary")
.debug_struct("part::Binary")
.field("mime", &self.interpreted) .field("mime", &self.interpreted)
.field("body", &format_args!("\"{}\"", String::from_utf8_lossy(self.body))) .field(
"body",
&format_args!("\"{}\"", String::from_utf8_lossy(self.body)),
)
.finish() .finish()
} }
} }

View file

@ -1,11 +1,7 @@
use nom::{ use nom::{branch::alt, combinator::map, IResult};
IResult,
branch::alt,
combinator::map,
};
use crate::mime;
use crate::imf; use crate::imf;
use crate::mime;
use crate::part::CompFieldList; use crate::part::CompFieldList;
pub enum MixedField<'a> { pub enum MixedField<'a> {
@ -61,5 +57,3 @@ pub fn mixed_field(input: &[u8]) -> IResult<&[u8], MixedField> {
map(imf::field::field, MixedField::IMF), map(imf::field::field, MixedField::IMF),
))(input) ))(input)
} }

View file

@ -1,6 +1,6 @@
pub mod field;
pub mod composite; pub mod composite;
pub mod discrete; pub mod discrete;
pub mod field;
use nom::{ use nom::{
branch::alt, branch::alt,
@ -14,10 +14,13 @@ use nom::{
use crate::header::CompFieldList; use crate::header::CompFieldList;
use crate::mime; use crate::mime;
use crate::mime::mime::AnyMIME; use crate::mime::mime::AnyMIME;
use crate::part::{
composite::{message, multipart, Message, Multipart},
discrete::{Binary, Text},
};
use crate::text::ascii::CRLF; use crate::text::ascii::CRLF;
use crate::text::boundary::boundary; use crate::text::boundary::boundary;
use crate::text::whitespace::obs_crlf; use crate::text::whitespace::obs_crlf;
use crate::part::{composite::{Multipart, Message, multipart, message}, discrete::{Text, Binary}};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum AnyPart<'a> { pub enum AnyPart<'a> {
@ -31,12 +34,26 @@ pub fn to_anypart<'a>(m: AnyMIME<'a>, rpart: &'a [u8]) -> AnyPart<'a> {
match m { match m {
AnyMIME::Mult(a) => map(multipart(a), AnyPart::Mult)(rpart) AnyMIME::Mult(a) => map(multipart(a), AnyPart::Mult)(rpart)
.map(|v| v.1) .map(|v| v.1)
.unwrap_or(AnyPart::Txt(Text { interpreted: mime::mime::Text::default(), body: rpart })), .unwrap_or(AnyPart::Txt(Text {
AnyMIME::Msg(a) => map(message(a), AnyPart::Msg)(rpart) interpreted: mime::mime::Text::default(),
body: rpart,
})),
AnyMIME::Msg(a) => {
map(message(a), AnyPart::Msg)(rpart)
.map(|v| v.1) .map(|v| v.1)
.unwrap_or(AnyPart::Txt(Text { interpreted: mime::mime::Text::default(), body: rpart })), .unwrap_or(AnyPart::Txt(Text {
AnyMIME::Txt(a) => AnyPart::Txt(Text { interpreted: a, body: rpart}), interpreted: mime::mime::Text::default(),
AnyMIME::Bin(a) => AnyPart::Bin(Binary{ interpreted: a, body: rpart }), body: rpart,
}))
}
AnyMIME::Txt(a) => AnyPart::Txt(Text {
interpreted: a,
body: rpart,
}),
AnyMIME::Bin(a) => AnyPart::Bin(Binary {
interpreted: a,
body: rpart,
}),
} }
} }

View file

@ -1,4 +1,10 @@
use nom::{branch::alt, bytes::complete::tag, combinator::{eof, opt}, sequence::tuple, IResult}; use nom::{
branch::alt,
bytes::complete::tag,
combinator::{eof, opt},
sequence::tuple,
IResult,
};
use crate::text::whitespace::obs_crlf; use crate::text::whitespace::obs_crlf;

View file

@ -13,8 +13,8 @@ use nom::{
}; };
use crate::text::ascii; use crate::text::ascii;
use crate::text::words;
use crate::text::whitespace::cfws; use crate::text::whitespace::cfws;
use crate::text::words;
pub fn encoded_word(input: &[u8]) -> IResult<&[u8], EncodedWord> { pub fn encoded_word(input: &[u8]) -> IResult<&[u8], EncodedWord> {
alt((encoded_word_quoted, encoded_word_base64))(input) alt((encoded_word_quoted, encoded_word_base64))(input)

View file

@ -1,4 +1,3 @@
use std::fmt;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, take_while1}, bytes::complete::{tag, take_while1},
@ -8,6 +7,7 @@ use nom::{
sequence::preceded, sequence::preceded,
IResult, IResult,
}; };
use std::fmt;
use crate::text::{ use crate::text::{
ascii, ascii,
@ -72,7 +72,9 @@ impl<'a> ToString for Word<'a> {
} }
impl<'a> fmt::Debug for Word<'a> { impl<'a> fmt::Debug for Word<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("Word").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("Word")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }
@ -103,7 +105,9 @@ impl<'a> ToString for Phrase<'a> {
} }
impl<'a> fmt::Debug for Phrase<'a> { impl<'a> fmt::Debug for Phrase<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("Phrase").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("Phrase")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }
@ -175,7 +179,9 @@ impl<'a> ToString for Unstructured<'a> {
} }
impl<'a> fmt::Debug for Unstructured<'a> { impl<'a> fmt::Debug for Unstructured<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("Unstructured").field(&format_args!("\"{}\"", self.to_string())).finish() fmt.debug_tuple("Unstructured")
.field(&format_args!("\"{}\"", self.to_string()))
.finish()
} }
} }