netlist_db/
_impl_display.rs

1use core::fmt;
2use std::fmt::Display;
3
4use super::*;
5
6pub struct FloatDisplay(pub f64);
7impl fmt::Display for FloatDisplay {
8    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9        write!(f, "{:.7e}", self.0)
10    }
11}
12
13pub struct TableFloatDisplay(pub f64);
14impl fmt::Display for TableFloatDisplay {
15    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16        if self.0.is_sign_positive() {
17            write!(f, " {: <13.7e}", self.0)
18        } else {
19            write!(f, "{: <14.7e}", self.0)
20        }
21    }
22}
23
24pub struct OptionDispaly<'a, T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result>(
25    pub &'a Option<T>,
26    pub F,
27);
28impl<T, F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result> Display for OptionDispaly<'_, T, F> {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        if let Some(t) = self.0 {
31            self.1(t, f)
32        } else {
33            Ok(())
34        }
35    }
36}
37
38pub fn display_wrap<
39    W: fmt::Write,
40    T,
41    I: Iterator<Item = T>,
42    SEP: fmt::Display,
43    F: FnMut(T, &mut W) -> fmt::Result,
44>(
45    f: &mut W,
46    iter: I,
47    mut fmt_one: F,
48    line_sep: SEP,
49    item_sep: char,
50    wrap_size: usize,
51) -> fmt::Result {
52    use itertools::Itertools as _;
53    for mut ts in iter.into_iter().chunks(wrap_size).into_iter() {
54        write!(f, "\n{line_sep}")?;
55        if let Some(first) = ts.next() {
56            fmt_one(first, f)?;
57            for t in ts {
58                write!(f, "{}", item_sep)?;
59                fmt_one(t, f)?;
60            }
61        }
62    }
63    Ok(())
64}
65
66pub fn display_inline<
67    W: fmt::Write,
68    T,
69    I: Iterator<Item = T>,
70    F: FnMut(T, &mut W) -> fmt::Result,
71>(
72    f: &mut W,
73    iter: I,
74    mut fmt_one: F,
75    sep: char,
76    skip_first_sep: bool,
77) -> fmt::Result {
78    let mut iter = iter.into_iter();
79    if skip_first_sep {
80        if let Some(first) = iter.next() {
81            fmt_one(first, f)?;
82        }
83    }
84    for t in iter {
85        write!(f, "{sep}")?;
86        fmt_one(t, f)?;
87    }
88    Ok(())
89}
90
91pub fn display_multiline<
92    W: fmt::Write,
93    T,
94    I: Iterator<Item = T>,
95    F: FnMut(T, &mut W) -> fmt::Result,
96>(
97    f: &mut W,
98    iter: I,
99    mut fmt_one: F,
100) -> fmt::Result {
101    for t in iter.into_iter() {
102        writeln!(f)?;
103        fmt_one(t, f)?;
104    }
105    Ok(())
106}
107
108impl fmt::Display for ast::Value<'_> {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        match self {
111            Self::Num(float) => write!(f, "{}", FloatDisplay(*float)),
112            Self::Expr(expr) => write!(f, "'{expr}'"),
113        }
114    }
115}
116impl fmt::Display for ast::KeyValue<'_> {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(f, "{}={}", self.k, self.v)
119    }
120}
121
122impl fmt::Display for ast::Token<'_> {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124        match self {
125            Self::KV(key_value) => write!(f, "{key_value}"),
126            Self::Value(v) => write!(f, "{v}"),
127            Self::V(name) => write!(f, "V({name})"),
128            Self::I(name) => write!(f, "I({name})"),
129        }
130    }
131}
132
133impl fmt::Display for ast::ModelType<'_> {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        match self {
136            Self::AMP => write!(f, "AMP"),
137            Self::C => write!(f, "C"),
138            Self::CORE => write!(f, "CORE"),
139            Self::D => write!(f, "D"),
140            Self::L => write!(f, "L"),
141            Self::NJF => write!(f, "NJF"),
142            Self::NMOS => write!(f, "NMOS"),
143            Self::NPN => write!(f, "NPN"),
144            Self::OPT => write!(f, "OPT"),
145            Self::PJF => write!(f, "PJF"),
146            Self::PMOS => write!(f, "PMOS"),
147            Self::PNP => write!(f, "PNP"),
148            Self::R => write!(f, "R"),
149            Self::U => write!(f, "U"),
150            Self::W => write!(f, "W"),
151            Self::S => write!(f, "S"),
152            Self::Unknown(span) => write!(f, "{span}"),
153        }
154    }
155}
156impl fmt::Display for ast::DataFiles<'_> {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        display_multiline(f, self.files.iter(), |file, f| {
159            write!(f, "+ FILE='{}'", file.file)?;
160            display_inline(
161                f,
162                file.pname_col_num.iter(),
163                |pname_col_num, f| write!(f, "{}={}", pname_col_num.pname, pname_col_num.col_num),
164                ' ',
165                false,
166            )
167        })?;
168        write!(
169            f,
170            "{}",
171            OptionDispaly(&self.out, |out, f| write!(f, "\n+ OUT='{out}'")),
172        )
173    }
174}
175
176impl fmt::Display for ast::Data<'_> {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        write!(f, ".DATA {}", self.name)?;
179        match &self.values {
180            ast::DataValues::InlineExpr { params, values } => {
181                write!(f, "\n+",)?;
182                display_inline(f, params.iter(), Display::fmt, ' ', false)?;
183                write!(f, " DATAFORM")?;
184                display_wrap(f, values.iter(), Display::fmt, "+ ", ' ', params.len())?;
185            }
186            ast::DataValues::InlineNum { params, values } => {
187                write!(f, "\n+",)?;
188                display_inline(f, params.iter(), Display::fmt, ' ', false)?;
189                display_wrap(
190                    f,
191                    values.iter(),
192                    |float: &f64, f: &mut fmt::Formatter<'_>| write!(f, "{}", FloatDisplay(*float)),
193                    "+ ",
194                    ' ',
195                    params.len(),
196                )?;
197            }
198            ast::DataValues::MER(data_files) => write!(f, " MER{data_files}")?,
199            ast::DataValues::LAM(data_files) => write!(f, " LAM{data_files}")?,
200        }
201        write!(f, "\n.ENDDATA")
202    }
203}
204
205impl fmt::Display for instance::Instance<'_> {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        write!(f, "{} {}", self.name, self.ctx)
208    }
209}
210
211impl fmt::Display for instance::InstanceCtx<'_> {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        match self {
214            instance::InstanceCtx::Resistor(resistor) => write!(f, "{resistor}"),
215            instance::InstanceCtx::Capacitor(capacitor) => write!(f, "{capacitor}"),
216            instance::InstanceCtx::Inductor(inductor) => write!(f, "{inductor}"),
217            instance::InstanceCtx::Voltage(voltage) => write!(f, "{voltage}"),
218            instance::InstanceCtx::Current(current) => write!(f, "{current}"),
219            instance::InstanceCtx::MOSFET(mosfet) => write!(f, "{mosfet}"),
220            instance::InstanceCtx::BJT(bjt) => write!(f, "{bjt}"),
221            instance::InstanceCtx::Diode(diode) => write!(f, "{diode}"),
222            instance::InstanceCtx::Subckt(subckt) => write!(f, "{subckt}"),
223            instance::InstanceCtx::Unknown {
224                r#type: _,
225                nodes,
226                params,
227            } => {
228                display_inline(f, nodes.iter(), Display::fmt, ' ', true)?;
229                display_inline(f, params.iter(), Display::fmt, ' ', false)
230            }
231        }
232    }
233}
234
235impl fmt::Display for instance::Subckt<'_> {
236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237        display_inline(f, self.nodes.iter(), Display::fmt, ' ', true)?;
238        write!(f, " {}", self.cktname)?;
239        display_inline(f, self.params.iter(), Display::fmt, ' ', false)
240    }
241}
242
243impl fmt::Display for instance::Voltage<'_> {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        write!(f, "{} {} {}", self.n1, self.n2, self.source,)
246    }
247}
248
249impl fmt::Display for instance::Current<'_> {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        write!(f, "{} {} {}", self.n1, self.n2, self.source,)
252    }
253}
254
255impl fmt::Display for instance::VoltageSource<'_> {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        match self {
258            instance::VoltageSource::Params(params) => {
259                display_inline(f, params.iter(), Display::fmt, ' ', false)
260            }
261            instance::VoltageSource::Value(value) => write!(f, "{value}"),
262            instance::VoltageSource::PWL(pwl) => write!(f, "{pwl}"),
263        }
264    }
265}
266
267impl fmt::Display for instance::CurrentSource<'_> {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        match self {
270            instance::CurrentSource::Params(params) => {
271                display_inline(f, params.iter(), Display::fmt, ' ', false)
272            }
273            instance::CurrentSource::Value(value) => write!(f, "{value}"),
274            instance::CurrentSource::PWL(pwl) => write!(f, "{pwl}"),
275        }
276    }
277}
278
279impl fmt::Display for instance::TimeValuePoint<'_> {
280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281        write!(f, "{} {}", self.time, self.value,)
282    }
283}
284
285impl fmt::Display for instance::PWL<'_> {
286    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287        write!(f, "PWL(",)?;
288        display_wrap(f, self.points.iter(), Display::fmt, "+ ", ' ', 1)?;
289        write!(f, ")",)
290    }
291}
292
293impl fmt::Display for instance::Resistor<'_> {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295        write!(f, "{} {} {}", self.n1, self.n2, self.value,)
296    }
297}
298impl fmt::Display for instance::Capacitor<'_> {
299    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300        write!(f, "{} {} {}", self.n1, self.n2, self.value,)
301    }
302}
303impl fmt::Display for instance::Inductor<'_> {
304    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305        write!(f, "{} {} {}", self.n1, self.n2, self.value,)
306    }
307}
308
309impl fmt::Display for instance::MOSFET<'_> {
310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311        write!(
312            f,
313            "{} {} {}{} {}",
314            self.nd,
315            self.ng,
316            self.ns,
317            OptionDispaly(&self.nb, |nb, f| write!(f, " {nb}")),
318            self.mname,
319        )?;
320        display_inline(f, self.params.iter(), Display::fmt, ' ', false)
321    }
322}
323
324impl fmt::Display for instance::BJT<'_> {
325    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326        write!(
327            f,
328            "{} {} {}{} {}",
329            self.nc,
330            self.nb,
331            self.ne,
332            OptionDispaly(&self.ns, |ns, f| write!(f, " {ns}")),
333            self.mname,
334        )?;
335        display_inline(f, self.params.iter(), Display::fmt, ' ', false)
336    }
337}
338
339impl fmt::Display for instance::Diode<'_> {
340    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341        write!(f, "{} {} {}", self.nplus, self.nminus, self.mname,)?;
342        display_inline(f, self.params.iter(), Display::fmt, ' ', false)
343    }
344}
345
346impl fmt::Display for ast::Model<'_> {
347    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348        write!(f, ".MODEL {} {}", self.name, self.model_type,)?;
349        display_wrap(f, self.params.iter(), Display::fmt, "+ ", ' ', 4)
350    }
351}
352
353impl fmt::Display for Subckt<'_> {
354    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355        write!(f, ".SUBCKT {}", self.name,)?;
356        display_inline(f, self.ports.iter(), Display::fmt, ' ', false)?;
357        display_inline(f, self.params.iter(), Display::fmt, ' ', false)?;
358        write!(f, "{}\n.ENDS {}", self.ast, self.name)
359    }
360}
361
362impl fmt::Display for ast::Unknwon<'_> {
363    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364        write!(f, ".{}", self.cmd)?;
365        display_inline(f, self.tokens.iter(), Display::fmt, ' ', false)
366    }
367}
368impl fmt::Display for ast::General<'_> {
369    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370        write!(f, ".{}", self.cmd)?;
371        display_inline(f, self.tokens.iter(), Display::fmt, ' ', false)
372    }
373}
374
375impl fmt::Display for AST<'_> {
376    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377        if !self.option.is_empty() {
378            write!(f, ".OPTION ",)?;
379            display_wrap(
380                f,
381                self.option.iter(),
382                |option: &(Cow<'_, str>, Option<ast::Value<'_>>), f: &mut fmt::Formatter<'_>| {
383                    if let Some(v) = &option.1 {
384                        write!(f, "{}={v}", option.0)
385                    } else {
386                        write!(f, "{}", option.0)
387                    }
388                },
389                "+ ",
390                ' ',
391                4,
392            )?;
393        }
394        if !self.param.is_empty() {
395            write!(f, "\n.PARAM ",)?;
396            display_wrap(f, self.param.iter(), Display::fmt, "+ ", ' ', 4)?;
397        }
398        display_multiline(f, self.model.iter(), Display::fmt)?;
399        display_multiline(f, self.subckt.values(), Display::fmt)?;
400        display_multiline(f, self.instance.iter(), Display::fmt)?;
401        display_multiline(
402            f,
403            self.init_condition.iter(),
404            |ic: &(Cow<'_, str>, ast::Value<'_>, Option<Cow<'_, str>>),
405             f: &mut fmt::Formatter<'_>| {
406                write!(f, ".IC V({})={}", ic.0, ic.1)?;
407                if let Some(subckt) = &ic.2 {
408                    write!(f, " suckt={subckt}")
409                } else {
410                    Ok(())
411                }
412            },
413        )?;
414        display_multiline(
415            f,
416            self.nodeset.iter(),
417            |ic: &(Cow<'_, str>, ast::Value<'_>, Option<Cow<'_, str>>),
418             f: &mut fmt::Formatter<'_>| {
419                write!(f, ".NODESET {}={}", ic.0, ic.1)?;
420                if let Some(subckt) = &ic.2 {
421                    write!(f, " suckt={subckt}")
422                } else {
423                    Ok(())
424                }
425            },
426        )?;
427        display_multiline(f, self.data.iter(), Display::fmt)?;
428        display_multiline(f, self.general.iter(), Display::fmt)?;
429        display_multiline(f, self.unknwon.iter(), Display::fmt)?;
430        Ok(())
431    }
432}
433
434impl fmt::Display for ast::GeneralCmd {
435    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
436        todo!()
437    }
438}