spacetimedb_sats/
satn.rs

1use crate::time_duration::TimeDuration;
2use crate::timestamp::Timestamp;
3use crate::uuid::Uuid;
4use crate::{i256, u256, AlgebraicType, AlgebraicValue, ProductValue, Serialize, SumValue, ValueWithType};
5use crate::{ser, ProductType, ProductTypeElement};
6use core::fmt;
7use core::fmt::Write as _;
8use derive_more::{Display, From, Into};
9use std::borrow::Cow;
10use std::marker::PhantomData;
11
12/// An extension trait for [`Serialize`] providing formatting methods.
13pub trait Satn: ser::Serialize {
14    /// Formats the value using the SATN data format into the formatter `f`.
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        Writer::with(f, |f| self.serialize(SatnFormatter { f }))?;
17        Ok(())
18    }
19
20    /// Formats the value using the postgres SATN(PsqlFormatter { f }, /* PsqlType */) formatter `f`.
21    fn fmt_psql(&self, f: &mut fmt::Formatter, ty: &PsqlType<'_>) -> fmt::Result {
22        Writer::with(f, |f| {
23            self.serialize(TypedSerializer {
24                ty,
25                f: &mut SqlFormatter {
26                    fmt: SatnFormatter { f },
27                    ty,
28                },
29            })
30        })?;
31        Ok(())
32    }
33
34    /// Formats the value using the SATN data format into the returned `String`.
35    fn to_satn(&self) -> String {
36        Wrapper::from_ref(self).to_string()
37    }
38
39    /// Pretty prints the value using the SATN data format into the returned `String`.
40    fn to_satn_pretty(&self) -> String {
41        format!("{:#}", Wrapper::from_ref(self))
42    }
43}
44
45impl<T: ser::Serialize + ?Sized> Satn for T {}
46
47/// A wrapper around a `T: Satn`
48/// providing `Display` and `Debug` implementations
49/// that uses the SATN formatting for `T`.
50#[repr(transparent)]
51pub struct Wrapper<T: ?Sized>(pub T);
52
53impl<T: ?Sized> Wrapper<T> {
54    /// Converts `&T` to `&Wrapper<T>`.
55    pub fn from_ref(t: &T) -> &Self {
56        // SAFETY: `repr(transparent)` turns the ABI of `T`
57        // into the same as `Self` so we can also cast `&T` to `&Self`.
58        unsafe { &*(t as *const T as *const Self) }
59    }
60}
61
62impl<T: Satn + ?Sized> fmt::Display for Wrapper<T> {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        self.0.fmt(f)
65    }
66}
67
68impl<T: Satn + ?Sized> fmt::Debug for Wrapper<T> {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        self.0.fmt(f)
71    }
72}
73
74/// A wrapper around a `T: Satn`
75/// providing `Display` and `Debug` implementations
76/// that uses postgres SATN formatting for `T`.
77pub struct PsqlWrapper<'a, T: ?Sized> {
78    pub ty: PsqlType<'a>,
79    pub value: T,
80}
81
82impl<T: ?Sized> PsqlWrapper<'_, T> {
83    /// Converts `&T` to `&PsqlWrapper<T>`.
84    pub fn from_ref(t: &T) -> &Self {
85        // SAFETY: `repr(transparent)` turns the ABI of `T`
86        // into the same as `Self` so we can also cast `&T` to `&Self`.
87        unsafe { &*(t as *const T as *const Self) }
88    }
89}
90
91impl<T: Satn + ?Sized> fmt::Display for PsqlWrapper<'_, T> {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        self.value.fmt_psql(f, &self.ty)
94    }
95}
96
97impl<T: Satn + ?Sized> fmt::Debug for PsqlWrapper<'_, T> {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        self.value.fmt_psql(f, &self.ty)
100    }
101}
102
103/// Wraps a writer for formatting lists separated by `SEP` into it.
104struct EntryWrapper<'a, 'f, const SEP: char> {
105    /// The writer we're formatting into.
106    fmt: Writer<'a, 'f>,
107    /// Whether there were any fields.
108    /// Initially `false` and then `true` after calling [`.entry(..)`](EntryWrapper::entry).
109    has_fields: bool,
110}
111
112impl<'a, 'f, const SEP: char> EntryWrapper<'a, 'f, SEP> {
113    /// Constructs the entry wrapper using the writer `fmt`.
114    fn new(fmt: Writer<'a, 'f>) -> Self {
115        Self { fmt, has_fields: false }
116    }
117
118    /// Formats another entry in the larger structure.
119    ///
120    /// The formatting for the element / entry itself is provided by the function `entry`.
121    fn entry(&mut self, entry: impl FnOnce(Writer) -> fmt::Result) -> fmt::Result {
122        let res = (|| match &mut self.fmt {
123            Writer::Pretty(f) => {
124                if !self.has_fields {
125                    f.write_char('\n')?;
126                }
127                f.state.indent += 1;
128                entry(Writer::Pretty(f.as_mut()))?;
129                f.write_char(SEP)?;
130                f.write_char('\n')?;
131                f.state.indent -= 1;
132                Ok(())
133            }
134            Writer::Normal(f) => {
135                if self.has_fields {
136                    f.write_char(SEP)?;
137                    f.write_char(' ')?;
138                }
139                entry(Writer::Normal(f))
140            }
141        })();
142        self.has_fields = true;
143        res
144    }
145}
146
147/// An implementation of [`fmt::Write`] supporting indented and non-idented formatting.
148enum Writer<'a, 'f> {
149    /// Uses the standard library's formatter i.e. plain formatting.
150    Normal(&'a mut fmt::Formatter<'f>),
151    /// Uses indented formatting.
152    Pretty(IndentedWriter<'a, 'f>),
153}
154
155impl<'f> Writer<'_, 'f> {
156    /// Provided with a formatter `f`, runs `func` provided with a `Writer`.
157    fn with<R>(f: &mut fmt::Formatter<'_>, func: impl FnOnce(Writer<'_, '_>) -> R) -> R {
158        let mut state;
159        // We use `alternate`, i.e., the `#` flag to let the user trigger pretty printing.
160        let f = if f.alternate() {
161            state = IndentState {
162                indent: 0,
163                on_newline: true,
164            };
165            Writer::Pretty(IndentedWriter { f, state: &mut state })
166        } else {
167            Writer::Normal(f)
168        };
169        func(f)
170    }
171
172    /// Returns a sub-writer without moving `self`.
173    fn as_mut(&mut self) -> Writer<'_, 'f> {
174        match self {
175            Writer::Normal(f) => Writer::Normal(f),
176            Writer::Pretty(f) => Writer::Pretty(f.as_mut()),
177        }
178    }
179}
180
181/// A formatter that adds decoration atop of the standard library's formatter.
182struct IndentedWriter<'a, 'f> {
183    f: &'a mut fmt::Formatter<'f>,
184    state: &'a mut IndentState,
185}
186
187/// The indentation state.
188struct IndentState {
189    /// Number of tab indentations to make.
190    indent: u32,
191    /// Whether we were last on a newline.
192    on_newline: bool,
193}
194
195impl<'f> IndentedWriter<'_, 'f> {
196    /// Returns a sub-writer without moving `self`.
197    fn as_mut(&mut self) -> IndentedWriter<'_, 'f> {
198        IndentedWriter {
199            f: self.f,
200            state: self.state,
201        }
202    }
203}
204
205impl fmt::Write for IndentedWriter<'_, '_> {
206    fn write_str(&mut self, s: &str) -> fmt::Result {
207        for s in s.split_inclusive('\n') {
208            if self.state.on_newline {
209                // Indent 4 characters times the indentation level.
210                for _ in 0..self.state.indent {
211                    self.f.write_str("    ")?;
212                }
213            }
214
215            self.state.on_newline = s.ends_with('\n');
216            self.f.write_str(s)?;
217        }
218        Ok(())
219    }
220}
221
222impl fmt::Write for Writer<'_, '_> {
223    fn write_str(&mut self, s: &str) -> fmt::Result {
224        match self {
225            Writer::Normal(f) => f.write_str(s),
226            Writer::Pretty(f) => f.write_str(s),
227        }
228    }
229}
230
231/// Provides the SATN data format implementing [`Serializer`](ser::Serializer).
232struct SatnFormatter<'a, 'f> {
233    /// The sink / writer / output / formatter.
234    f: Writer<'a, 'f>,
235}
236
237impl SatnFormatter<'_, '_> {
238    fn ser_variant<T: ser::Serialize + ?Sized>(
239        &mut self,
240        _tag: u8,
241        name: Option<&str>,
242        value: &T,
243    ) -> Result<(), SatnError> {
244        write!(self, "(")?;
245        EntryWrapper::<','>::new(self.f.as_mut()).entry(|mut f| {
246            if let Some(name) = name {
247                write!(f, "{name}")?;
248            }
249            write!(f, " = ")?;
250            value.serialize(SatnFormatter { f })?;
251            Ok(())
252        })?;
253        write!(self, ")")?;
254
255        Ok(())
256    }
257}
258/// An error occurred during serialization to the SATS data format.
259#[derive(From, Into)]
260pub struct SatnError(fmt::Error);
261
262impl ser::Error for SatnError {
263    fn custom<T: fmt::Display>(_msg: T) -> Self {
264        Self(fmt::Error)
265    }
266}
267
268impl SatnFormatter<'_, '_> {
269    /// Writes `args` formatted to `self`.
270    #[inline(always)]
271    fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), SatnError> {
272        self.f.write_fmt(args)?;
273        Ok(())
274    }
275}
276
277impl<'a, 'f> ser::Serializer for SatnFormatter<'a, 'f> {
278    type Ok = ();
279    type Error = SatnError;
280    type SerializeArray = ArrayFormatter<'a, 'f>;
281    type SerializeSeqProduct = SeqFormatter<'a, 'f>;
282    type SerializeNamedProduct = NamedFormatter<'a, 'f>;
283
284    fn serialize_bool(mut self, v: bool) -> Result<Self::Ok, Self::Error> {
285        write!(self, "{v}")
286    }
287    fn serialize_u8(mut self, v: u8) -> Result<Self::Ok, Self::Error> {
288        write!(self, "{v}")
289    }
290    fn serialize_u16(mut self, v: u16) -> Result<Self::Ok, Self::Error> {
291        write!(self, "{v}")
292    }
293    fn serialize_u32(mut self, v: u32) -> Result<Self::Ok, Self::Error> {
294        write!(self, "{v}")
295    }
296    fn serialize_u64(mut self, v: u64) -> Result<Self::Ok, Self::Error> {
297        write!(self, "{v}")
298    }
299    fn serialize_u128(mut self, v: u128) -> Result<Self::Ok, Self::Error> {
300        write!(self, "{v}")
301    }
302    fn serialize_u256(mut self, v: u256) -> Result<Self::Ok, Self::Error> {
303        write!(self, "{v}")
304    }
305    fn serialize_i8(mut self, v: i8) -> Result<Self::Ok, Self::Error> {
306        write!(self, "{v}")
307    }
308    fn serialize_i16(mut self, v: i16) -> Result<Self::Ok, Self::Error> {
309        write!(self, "{v}")
310    }
311    fn serialize_i32(mut self, v: i32) -> Result<Self::Ok, Self::Error> {
312        write!(self, "{v}")
313    }
314    fn serialize_i64(mut self, v: i64) -> Result<Self::Ok, Self::Error> {
315        write!(self, "{v}")
316    }
317    fn serialize_i128(mut self, v: i128) -> Result<Self::Ok, Self::Error> {
318        write!(self, "{v}")
319    }
320    fn serialize_i256(mut self, v: i256) -> Result<Self::Ok, Self::Error> {
321        write!(self, "{v}")
322    }
323    fn serialize_f32(mut self, v: f32) -> Result<Self::Ok, Self::Error> {
324        write!(self, "{v}")
325    }
326    fn serialize_f64(mut self, v: f64) -> Result<Self::Ok, Self::Error> {
327        write!(self, "{v}")
328    }
329
330    fn serialize_str(mut self, v: &str) -> Result<Self::Ok, Self::Error> {
331        write!(self, "\"{v}\"")
332    }
333
334    fn serialize_bytes(mut self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
335        write!(self, "0x{}", hex::encode(v))
336    }
337
338    fn serialize_array(mut self, _len: usize) -> Result<Self::SerializeArray, Self::Error> {
339        write!(self, "[")?; // Closed via `.end()`.
340        Ok(ArrayFormatter {
341            f: EntryWrapper::new(self.f),
342        })
343    }
344
345    fn serialize_seq_product(self, len: usize) -> Result<Self::SerializeSeqProduct, Self::Error> {
346        // Delegate to named products handling of element formatting.
347        self.serialize_named_product(len).map(|inner| SeqFormatter { inner })
348    }
349
350    fn serialize_named_product(mut self, _len: usize) -> Result<Self::SerializeNamedProduct, Self::Error> {
351        write!(self, "(")?; // Closed via `.end()`.
352        Ok(NamedFormatter {
353            f: EntryWrapper::new(self.f),
354            idx: 0,
355        })
356    }
357
358    fn serialize_variant<T: ser::Serialize + ?Sized>(
359        mut self,
360        tag: u8,
361        name: Option<&str>,
362        value: &T,
363    ) -> Result<Self::Ok, Self::Error> {
364        self.ser_variant(tag, name, value)
365    }
366}
367
368/// Defines the SATN formatting for arrays.
369struct ArrayFormatter<'a, 'f> {
370    /// The formatter for each element separating elements by a `,`.
371    f: EntryWrapper<'a, 'f, ','>,
372}
373
374impl ser::SerializeArray for ArrayFormatter<'_, '_> {
375    type Ok = ();
376    type Error = SatnError;
377
378    fn serialize_element<T: ser::Serialize + ?Sized>(&mut self, elem: &T) -> Result<(), Self::Error> {
379        self.f.entry(|f| elem.serialize(SatnFormatter { f }).map_err(|e| e.0))?;
380        Ok(())
381    }
382
383    fn end(mut self) -> Result<Self::Ok, Self::Error> {
384        write!(self.f.fmt, "]")?;
385        Ok(())
386    }
387}
388
389/// Provides the data format for unnamed products for SATN.
390struct SeqFormatter<'a, 'f> {
391    /// Delegates to the named format.
392    inner: NamedFormatter<'a, 'f>,
393}
394
395impl ser::SerializeSeqProduct for SeqFormatter<'_, '_> {
396    type Ok = ();
397    type Error = SatnError;
398
399    fn serialize_element<T: ser::Serialize + ?Sized>(&mut self, elem: &T) -> Result<(), Self::Error> {
400        ser::SerializeNamedProduct::serialize_element(&mut self.inner, None, elem)
401    }
402
403    fn end(self) -> Result<Self::Ok, Self::Error> {
404        ser::SerializeNamedProduct::end(self.inner)
405    }
406}
407
408/// Provides the data format for named products for SATN.
409struct NamedFormatter<'a, 'f> {
410    /// The formatter for each element separating elements by a `,`.
411    f: EntryWrapper<'a, 'f, ','>,
412    /// The index of the element.
413    idx: usize,
414}
415
416impl ser::SerializeNamedProduct for NamedFormatter<'_, '_> {
417    type Ok = ();
418    type Error = SatnError;
419
420    fn serialize_element<T: ser::Serialize + ?Sized>(
421        &mut self,
422        name: Option<&str>,
423        elem: &T,
424    ) -> Result<(), Self::Error> {
425        let res = self.f.entry(|mut f| {
426            // Format the name or use the index if unnamed.
427            if let Some(name) = name {
428                write!(f, "{name}")?;
429            } else {
430                write!(f, "{}", self.idx)?;
431            }
432            write!(f, " = ")?;
433            elem.serialize(SatnFormatter { f })?;
434            Ok(())
435        });
436        self.idx += 1;
437        res?;
438        Ok(())
439    }
440
441    fn end(mut self) -> Result<Self::Ok, Self::Error> {
442        write!(self.f.fmt, ")")?;
443        Ok(())
444    }
445}
446
447/// Which client is used to format the `SQL` output?
448#[derive(PartialEq, Copy, Clone, Debug)]
449pub enum PsqlClient {
450    SpacetimeDB,
451    Postgres,
452}
453
454pub struct PsqlChars {
455    pub start: char,
456    pub sep: &'static str,
457    pub end: char,
458    pub quote: &'static str,
459}
460
461impl PsqlClient {
462    pub fn format_chars(&self) -> PsqlChars {
463        match self {
464            PsqlClient::SpacetimeDB => PsqlChars {
465                start: '(',
466                sep: " =",
467                end: ')',
468                quote: "",
469            },
470            PsqlClient::Postgres => PsqlChars {
471                start: '{',
472                sep: ":",
473                end: '}',
474                quote: "\"",
475            },
476        }
477    }
478}
479
480/// How format of the `SQL` output?
481#[derive(Debug, Copy, Clone, PartialEq, Display)]
482pub enum PsqlPrintFmt {
483    /// Print as `hex` format
484    Hex,
485    /// Print as [`Timestamp`] format
486    Timestamp,
487    /// Print as [`TimeDuration`] format
488    Duration,
489    /// Print as `UUID` format
490    Uuid,
491    /// Print as `Satn` format
492    Satn,
493}
494
495impl PsqlPrintFmt {
496    pub fn is_special(&self) -> bool {
497        self != &PsqlPrintFmt::Satn
498    }
499    /// Returns if the type is a special type
500    ///
501    /// Is required to check both the enclosing type and the inner element type
502    pub fn use_fmt(tuple: &ProductType, field: &ProductTypeElement, name: Option<&str>) -> PsqlPrintFmt {
503        if tuple.is_identity()
504            || tuple.is_connection_id()
505            || field.algebraic_type.is_identity()
506            || field.algebraic_type.is_connection_id()
507            || name.map(ProductType::is_identity_tag).unwrap_or_default()
508            || name.map(ProductType::is_connection_id_tag).unwrap_or_default()
509        {
510            return PsqlPrintFmt::Hex;
511        };
512
513        if tuple.is_timestamp()
514            || field.algebraic_type.is_timestamp()
515            || name.map(ProductType::is_timestamp_tag).unwrap_or_default()
516        {
517            return PsqlPrintFmt::Timestamp;
518        };
519
520        if tuple.is_time_duration()
521            || field.algebraic_type.is_time_duration()
522            || name.map(ProductType::is_time_duration_tag).unwrap_or_default()
523        {
524            return PsqlPrintFmt::Duration;
525        };
526
527        if tuple.is_uuid() || field.algebraic_type.is_uuid() || name.map(ProductType::is_uuid_tag).unwrap_or_default() {
528            return PsqlPrintFmt::Uuid;
529        };
530
531        PsqlPrintFmt::Satn
532    }
533}
534
535/// A wrapper that remember the `header` of the tuple/struct and the current field
536#[derive(Debug, Clone)]
537pub struct PsqlType<'a> {
538    /// The client used to format the output
539    pub client: PsqlClient,
540    /// The header of the tuple/struct
541    pub tuple: &'a ProductType,
542    /// The current field
543    pub field: &'a ProductTypeElement,
544    /// The index of the field in the tuple/struct
545    pub idx: usize,
546}
547
548impl PsqlType<'_> {
549    /// Returns if the type is a special type
550    ///
551    /// Is required to check both the enclosing type and the inner element type
552    pub fn use_fmt(&self) -> PsqlPrintFmt {
553        PsqlPrintFmt::use_fmt(self.tuple, self.field, None)
554    }
555}
556
557/// An implementation of [`Serializer`](ser::Serializer) for `SQL` output.
558pub struct SqlFormatter<'a, 'f> {
559    fmt: SatnFormatter<'a, 'f>,
560    ty: &'a PsqlType<'a>,
561}
562
563/// A trait for writing values, after the special types has been determined.
564///
565/// This is used to write values that could have different representations depending on the output format,
566/// as defined by [`PsqlClient`] and [`PsqlPrintFmt`].
567pub trait TypedWriter {
568    type Error: ser::Error;
569
570    /// Writes a value using [`ser::Serializer`]
571    fn write<W: fmt::Display>(&mut self, value: W) -> Result<(), Self::Error>;
572
573    // Values that need special handling:
574
575    fn write_bool(&mut self, value: bool) -> Result<(), Self::Error>;
576    fn write_string(&mut self, value: &str) -> Result<(), Self::Error>;
577    fn write_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error>;
578    fn write_hex(&mut self, value: &[u8]) -> Result<(), Self::Error>;
579    fn write_timestamp(&mut self, value: Timestamp) -> Result<(), Self::Error>;
580    fn write_duration(&mut self, value: TimeDuration) -> Result<(), Self::Error>;
581    fn write_uuid(&mut self, value: Uuid) -> Result<(), Self::Error>;
582    /// Writes a value as an alternative record format, e.g., for use `JSON` inside `SQL`.
583    fn write_alt_record(
584        &mut self,
585        _ty: &PsqlType,
586        _value: &ValueWithType<'_, ProductValue>,
587    ) -> Result<bool, Self::Error> {
588        Ok(false)
589    }
590
591    fn write_record(
592        &mut self,
593        fields: Vec<(Cow<str>, PsqlType, ValueWithType<AlgebraicValue>)>,
594    ) -> Result<(), Self::Error>;
595
596    fn write_variant(
597        &mut self,
598        tag: u8,
599        ty: PsqlType,
600        name: Option<&str>,
601        value: ValueWithType<AlgebraicValue>,
602    ) -> Result<(), Self::Error>;
603}
604
605/// A formatter for arrays that uses the `TypedWriter` trait to write elements.
606pub struct TypedArrayFormatter<'a, 'f, F> {
607    ty: &'a PsqlType<'a>,
608    f: &'f mut F,
609}
610
611impl<F: TypedWriter> ser::SerializeArray for TypedArrayFormatter<'_, '_, F> {
612    type Ok = ();
613    type Error = F::Error;
614
615    fn serialize_element<T: ser::Serialize + ?Sized>(&mut self, elem: &T) -> Result<(), Self::Error> {
616        elem.serialize(TypedSerializer { ty: self.ty, f: self.f })?;
617        Ok(())
618    }
619
620    fn end(self) -> Result<Self::Ok, Self::Error> {
621        Ok(())
622    }
623}
624
625/// A formatter for sequences that uses the `TypedWriter` trait to write elements.
626pub struct TypedSeqFormatter<'a, 'f, F> {
627    ty: &'a PsqlType<'a>,
628    f: &'f mut F,
629}
630
631impl<F: TypedWriter> ser::SerializeSeqProduct for TypedSeqFormatter<'_, '_, F> {
632    type Ok = ();
633    type Error = F::Error;
634
635    fn serialize_element<T: ser::Serialize + ?Sized>(&mut self, elem: &T) -> Result<(), Self::Error> {
636        elem.serialize(TypedSerializer { ty: self.ty, f: self.f })?;
637        Ok(())
638    }
639
640    fn end(self) -> Result<Self::Ok, Self::Error> {
641        Ok(())
642    }
643}
644
645/// A formatter for named products that uses the `TypedWriter` trait to write elements.
646pub struct TypedNamedProductFormatter<F> {
647    f: PhantomData<F>,
648}
649
650impl<F: TypedWriter> ser::SerializeNamedProduct for TypedNamedProductFormatter<F> {
651    type Ok = ();
652    type Error = F::Error;
653
654    fn serialize_element<T: ser::Serialize + ?Sized>(
655        &mut self,
656        _name: Option<&str>,
657        _elem: &T,
658    ) -> Result<(), Self::Error> {
659        Ok(())
660    }
661
662    fn end(self) -> Result<Self::Ok, Self::Error> {
663        Ok(())
664    }
665}
666
667/// A serializer that uses the `TypedWriter` trait to serialize values
668pub struct TypedSerializer<'a, 'f, F> {
669    pub ty: &'a PsqlType<'a>,
670    pub f: &'f mut F,
671}
672
673impl<'a, 'f, F: TypedWriter> ser::Serializer for TypedSerializer<'a, 'f, F> {
674    type Ok = ();
675    type Error = F::Error;
676    type SerializeArray = TypedArrayFormatter<'a, 'f, F>;
677    type SerializeSeqProduct = TypedSeqFormatter<'a, 'f, F>;
678    type SerializeNamedProduct = TypedNamedProductFormatter<F>;
679
680    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
681        self.f.write_bool(v)
682    }
683
684    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
685        self.f.write(v)
686    }
687
688    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
689        self.f.write(v)
690    }
691
692    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
693        self.f.write(v)
694    }
695
696    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
697        self.f.write(v)
698    }
699
700    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
701        match self.ty.use_fmt() {
702            PsqlPrintFmt::Hex => self.f.write_hex(&v.to_be_bytes()),
703            PsqlPrintFmt::Uuid => self.f.write_uuid(Uuid::from_u128(v)),
704            _ => self.f.write(v),
705        }
706    }
707
708    fn serialize_u256(self, v: u256) -> Result<Self::Ok, Self::Error> {
709        match self.ty.use_fmt() {
710            PsqlPrintFmt::Hex => self.f.write_hex(&v.to_be_bytes()),
711            _ => self.f.write(v),
712        }
713    }
714
715    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
716        self.f.write(v)
717    }
718
719    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
720        self.f.write(v)
721    }
722
723    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
724        self.f.write(v)
725    }
726
727    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
728        match self.ty.use_fmt() {
729            PsqlPrintFmt::Duration => self.f.write_duration(TimeDuration::from_micros(v)),
730            PsqlPrintFmt::Timestamp => self.f.write_timestamp(Timestamp::from_micros_since_unix_epoch(v)),
731            _ => self.f.write(v),
732        }
733    }
734
735    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
736        self.f.write(v)
737    }
738
739    fn serialize_i256(self, v: i256) -> Result<Self::Ok, Self::Error> {
740        self.f.write(v)
741    }
742
743    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
744        self.f.write(v)
745    }
746
747    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
748        self.f.write(v)
749    }
750
751    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
752        self.f.write_string(v)
753    }
754
755    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
756        if self.ty.use_fmt() == PsqlPrintFmt::Satn {
757            self.f.write_hex(v)
758        } else {
759            self.f.write_bytes(v)
760        }
761    }
762
763    fn serialize_array(self, _len: usize) -> Result<Self::SerializeArray, Self::Error> {
764        Ok(TypedArrayFormatter { ty: self.ty, f: self.f })
765    }
766
767    fn serialize_seq_product(self, _len: usize) -> Result<Self::SerializeSeqProduct, Self::Error> {
768        Ok(TypedSeqFormatter { ty: self.ty, f: self.f })
769    }
770
771    fn serialize_named_product(self, _len: usize) -> Result<Self::SerializeNamedProduct, Self::Error> {
772        unreachable!("This should never be called, use `serialize_named_product_raw` instead.");
773    }
774
775    fn serialize_named_product_raw(self, value: &ValueWithType<'_, ProductValue>) -> Result<Self::Ok, Self::Error> {
776        let val = &value.val.elements;
777        assert_eq!(val.len(), value.ty().elements.len());
778        // If the value is a special type, we can write it directly
779        if self.ty.use_fmt().is_special() {
780            // Is a nested product type?
781            // We need to check for both the  enclosing(`self.ty`) type and the inner element type.
782            let (tuple, field) = if let Some(product) = self.ty.field.algebraic_type.as_product() {
783                (product, &product.elements[0])
784            } else {
785                (self.ty.tuple, self.ty.field)
786            };
787            return value.val.serialize(TypedSerializer {
788                ty: &PsqlType {
789                    client: self.ty.client,
790                    tuple,
791                    field,
792                    idx: self.ty.idx,
793                },
794                f: self.f,
795            });
796        }
797        // Allow to switch to an alternative record format, for example to write a `JSON` record.
798        if self.f.write_alt_record(self.ty, value)? {
799            return Ok(());
800        }
801        let mut record = Vec::with_capacity(val.len());
802
803        for (idx, (val, field)) in val.iter().zip(&*value.ty().elements).enumerate() {
804            let ty = PsqlType {
805                client: self.ty.client,
806                tuple: value.ty(),
807                field,
808                idx,
809            };
810            record.push((
811                field
812                    .name()
813                    .map(Cow::from)
814                    .unwrap_or_else(|| Cow::from(format!("col_{idx}"))),
815                ty,
816                value.with(&field.algebraic_type, val),
817            ));
818        }
819        self.f.write_record(record)
820    }
821
822    fn serialize_variant_raw(self, sum: &ValueWithType<'_, SumValue>) -> Result<Self::Ok, Self::Error> {
823        let sv = sum.value();
824        let (tag, val) = (sv.tag, &*sv.value);
825        let var_ty = &sum.ty().variants[tag as usize]; // Extract the variant type by tag.
826        let product = ProductType::from([AlgebraicType::sum(sum.ty().clone())]);
827        let ty = PsqlType {
828            client: self.ty.client,
829            tuple: &product,
830            field: &product.elements[0],
831            idx: 0,
832        };
833        self.f
834            .write_variant(tag, ty, var_ty.name(), sum.with(&var_ty.algebraic_type, val))
835    }
836
837    fn serialize_variant<T: Serialize + ?Sized>(
838        self,
839        _tag: u8,
840        _name: Option<&str>,
841        _value: &T,
842    ) -> Result<Self::Ok, Self::Error> {
843        unreachable!("Use `serialize_variant_raw` instead.");
844    }
845}
846
847impl TypedWriter for SqlFormatter<'_, '_> {
848    type Error = SatnError;
849
850    fn write<W: fmt::Display>(&mut self, value: W) -> Result<(), Self::Error> {
851        write!(self.fmt, "{value}")
852    }
853
854    fn write_bool(&mut self, value: bool) -> Result<(), Self::Error> {
855        write!(self.fmt, "{value}")
856    }
857
858    fn write_string(&mut self, value: &str) -> Result<(), Self::Error> {
859        write!(self.fmt, "\"{value}\"")
860    }
861
862    fn write_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
863        self.write_hex(value)
864    }
865
866    fn write_hex(&mut self, value: &[u8]) -> Result<(), Self::Error> {
867        match self.ty.client {
868            PsqlClient::SpacetimeDB => write!(self.fmt, "0x{}", hex::encode(value)),
869            PsqlClient::Postgres => write!(self.fmt, "\"0x{}\"", hex::encode(value)),
870        }
871    }
872
873    fn write_timestamp(&mut self, value: Timestamp) -> Result<(), Self::Error> {
874        match self.ty.client {
875            PsqlClient::SpacetimeDB => write!(self.fmt, "{}", value.to_rfc3339().unwrap()),
876            PsqlClient::Postgres => write!(self.fmt, "\"{}\"", value.to_rfc3339().unwrap()),
877        }
878    }
879
880    fn write_duration(&mut self, value: TimeDuration) -> Result<(), Self::Error> {
881        match self.ty.client {
882            PsqlClient::SpacetimeDB => write!(self.fmt, "{value}"),
883            PsqlClient::Postgres => write!(self.fmt, "\"{}\"", value.to_iso8601()),
884        }
885    }
886
887    fn write_uuid(&mut self, value: Uuid) -> Result<(), Self::Error> {
888        write!(self.fmt, "\"{value}\"")
889    }
890
891    fn write_record(
892        &mut self,
893        fields: Vec<(Cow<str>, PsqlType<'_>, ValueWithType<AlgebraicValue>)>,
894    ) -> Result<(), Self::Error> {
895        let PsqlChars { start, sep, end, quote } = self.ty.client.format_chars();
896        write!(self.fmt, "{start}")?;
897        for (idx, (name, ty, value)) in fields.into_iter().enumerate() {
898            if idx > 0 {
899                write!(self.fmt, ", ")?;
900            }
901            write!(self.fmt, "{quote}{name}{quote}{sep} ")?;
902
903            // Serialize the value
904            value.serialize(TypedSerializer { ty: &ty, f: self })?;
905        }
906        write!(self.fmt, "{end}")?;
907        Ok(())
908    }
909
910    fn write_variant(
911        &mut self,
912        tag: u8,
913        ty: PsqlType,
914        name: Option<&str>,
915        value: ValueWithType<AlgebraicValue>,
916    ) -> Result<(), Self::Error> {
917        self.write_record(vec![(
918            name.map(Cow::from).unwrap_or_else(|| Cow::from(format!("col_{tag}"))),
919            ty,
920            value,
921        )])
922    }
923}