Skip to main content

deser_env/
de.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::ffi::OsString;
4use std::sync::Arc;
5
6use deser_core::Text;
7use deser_core::de::{
8    self, Deserialize, DeserializeDriver, DeserializeOwned, DuplicateKeys, LexicalRules,
9};
10use deser_core::{Atom, Bytes, ContainerShape, Error, ErrorKind, Event};
11
12use crate::{Case, EnvVar};
13
14/// Configures how environment variables are deserialized.
15///
16/// The configuration is independent of the environment so it can be
17/// created once (even as a constant) and used many times.  The methods
18/// [`from_env`](Self::from_env) and [`from_vars`](Self::from_vars) work like
19/// the functions of the same name.
20///
21/// ```
22/// use std::collections::BTreeMap;
23/// use deser_env::DeserializerConfig;
24///
25/// const CONFIG: DeserializerConfig =
26///     DeserializerConfig::builder().separator("_").build();
27/// let value: BTreeMap<String, BTreeMap<String, u32>> =
28///     CONFIG.from_vars("APP_", [("APP_SERVER_PORT", "80")]).unwrap();
29/// assert_eq!(value["server"]["port"], 80);
30/// ```
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct DeserializerConfig {
33    separator: &'static str,
34    case: Case,
35    max_depth: usize,
36    context: deser_core::Context,
37}
38
39impl Default for DeserializerConfig {
40    fn default() -> DeserializerConfig {
41        DeserializerConfig::new()
42    }
43}
44
45impl DeserializerConfig {
46    /// Creates the default configuration.
47    pub const fn new() -> DeserializerConfig {
48        DeserializerConfig {
49            separator: "__",
50            case: Case::Upper,
51            max_depth: 16,
52            context: deser_core::Context::new(),
53        }
54    }
55
56    /// Returns a builder for the configuration (see [`DeserializerConfigBuilder`]).
57    pub const fn builder() -> DeserializerConfigBuilder {
58        DeserializerConfigBuilder::new()
59    }
60
61    /// Returns a builder that starts with this configuration.
62    pub const fn into_builder(self) -> DeserializerConfigBuilder {
63        DeserializerConfigBuilder { value: self }
64    }
65
66    /// Sets the context the values are deserialized in.
67    ///
68    /// The values of the context are the defaults of the extension values
69    /// of the state (see [`Context`](deser_core::Context)), for instance
70    /// the variants of open enums.  The deserializers and readers created
71    /// with the configuration use this context.  A context set
72    /// on the driver takes precedence.
73    pub fn set_context(&mut self, context: deser_core::Context) {
74        self.context = context;
75    }
76
77    /// Returns the context the values are deserialized in.
78    pub fn context(&self) -> &deser_core::Context {
79        &self.context
80    }
81
82    /// Sets the separator of nested keys.
83    ///
84    /// The default is `__` (`APP_SERVER__PORT` is `server.port`).  A single
85    /// `_` cannot be told apart from the underscores in names, so
86    /// `APP_MAX_CONNECTIONS` would be `max.connections`.  The empty string
87    /// disables nesting, names are keys as they are.
88    pub const fn set_separator(&mut self, separator: &'static str) {
89        self.separator = separator;
90    }
91
92    /// Sets how the case of names maps onto keys.
93    ///
94    /// The default is [`Case::Upper`] which lowercases the names.
95    pub const fn set_case(&mut self, case: Case) {
96        self.case = case;
97    }
98
99    /// Sets how deeply keys can be nested.
100    ///
101    /// This is the number of separators in a name (after the prefix).
102    /// Names that are nested deeper are an error.  The default is 16.
103    pub const fn set_max_depth(&mut self, depth: usize) {
104        self.max_depth = depth;
105    }
106
107    /// Deserializes a value from the environment variables with a prefix.
108    ///
109    /// See [`from_env`](crate::from_env).
110    pub fn from_env<T: DeserializeOwned>(&self, prefix: &str) -> Result<T, Error> {
111        Deserializer::from_env_with_config(prefix, self.clone()).deserialize()
112    }
113
114    /// Deserializes a value from the given variables with a prefix.
115    ///
116    /// See [`from_vars`](crate::from_vars).
117    pub fn from_vars<'a, T, I, K, V>(&self, prefix: &str, vars: I) -> Result<T, Error>
118    where
119        T: Deserialize<'a>,
120        I: IntoIterator<Item = (K, V)>,
121        K: Into<Cow<'a, str>>,
122        V: Into<Cow<'a, str>>,
123    {
124        Deserializer::from_vars_with_config(prefix, vars, self.clone()).deserialize()
125    }
126}
127
128/// Builds a [`DeserializerConfig`].
129///
130/// The methods have the names of the setters of [`DeserializerConfig`] (without `set_`).
131#[derive(Debug, Clone)]
132#[must_use]
133pub struct DeserializerConfigBuilder {
134    value: DeserializerConfig,
135}
136
137impl DeserializerConfigBuilder {
138    /// Creates a builder that starts with the default.
139    pub const fn new() -> DeserializerConfigBuilder {
140        DeserializerConfigBuilder {
141            value: DeserializerConfig::new(),
142        }
143    }
144
145    /// Sets the separator of nested keys.
146    ///
147    /// See [`DeserializerConfig::set_separator`].
148    pub const fn separator(mut self, separator: &'static str) -> DeserializerConfigBuilder {
149        self.value.set_separator(separator);
150        self
151    }
152
153    /// Sets how the case of names maps onto keys.
154    ///
155    /// See [`DeserializerConfig::set_case`].
156    pub const fn case(mut self, case: Case) -> DeserializerConfigBuilder {
157        self.value.set_case(case);
158        self
159    }
160
161    /// Sets how deeply keys can be nested.
162    ///
163    /// See [`DeserializerConfig::set_max_depth`].
164    pub const fn max_depth(mut self, depth: usize) -> DeserializerConfigBuilder {
165        self.value.set_max_depth(depth);
166        self
167    }
168
169    /// Sets the context the values are deserialized in.
170    ///
171    /// See [`DeserializerConfig::set_context`].
172    pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder {
173        self.value.set_context(context);
174        self
175    }
176
177    /// Returns the built [`DeserializerConfig`].
178    pub const fn build(self) -> DeserializerConfig {
179        // the value cannot be moved out of the builder in a const fn as the
180        // builder needs dropping (the context has a destructor)
181        // SAFETY: the value is read once and the builder is forgotten
182        let value = unsafe { core::ptr::read(&self.value) };
183        core::mem::forget(self);
184        value
185    }
186}
187
188impl Default for DeserializerConfigBuilder {
189    fn default() -> DeserializerConfigBuilder {
190        DeserializerConfigBuilder::new()
191    }
192}
193
194/// The value of a variable.
195enum Value<'a> {
196    Text(Cow<'a, str>),
197    /// A value that is not valid unicode.
198    Bytes(Vec<u8>),
199}
200
201/// A variable with a name that starts with the prefix.
202struct Var<'a> {
203    /// The full name (for errors).
204    name: Arc<str>,
205    /// The length of the prefix in the name.
206    prefix_len: usize,
207    value: Value<'a>,
208}
209
210/// Deserializes environment variables.
211///
212/// The variables are read when the deserializer is created.  Most of the
213/// time the [`from_env`](crate::from_env) and
214/// [`from_vars`](crate::from_vars) functions (or the methods of the same
215/// name on [`DeserializerConfig`]) are all that is needed.  The deserializer
216/// is useful to configure the driver, for instance to add layers, or to
217/// update a value (see [`update`](deser_core::de::Deserializer::update)):
218///
219/// ```
220/// use deser::de::Deserializer as _;
221/// use deser_env::Deserializer;
222///
223/// #[derive(Debug, deser::Deserialize)]
224/// struct Config {
225///     host: String,
226///     port: u16,
227/// }
228///
229/// let mut config = Config { host: "localhost".into(), port: 80 };
230/// Deserializer::from_vars("APP_", [("APP_PORT", "8080")])
231///     .update(&mut config)
232///     .unwrap();
233/// assert_eq!(config.host, "localhost");
234/// assert_eq!(config.port, 8080);
235/// ```
236pub struct Deserializer<'a> {
237    vars: Vec<Var<'a>>,
238    /// An error that is reported instead of deserializing.
239    error: Option<Error>,
240    config: DeserializerConfig,
241}
242
243impl Deserializer<'static> {
244    /// Creates a deserializer for the environment variables with a prefix.
245    pub fn from_env(prefix: &str) -> Deserializer<'static> {
246        Deserializer::from_env_with_config(prefix, DeserializerConfig::new())
247    }
248
249    /// Creates a deserializer for the environment variables with a prefix
250    /// and the given configuration.
251    ///
252    /// Variables with names that are not valid unicode are skipped unless
253    /// they start with the prefix, which is an error.  Values that are not
254    /// valid unicode are passed on as bytes on Unix and are an error on
255    /// other platforms.
256    pub fn from_env_with_config(prefix: &str, config: DeserializerConfig) -> Deserializer<'static> {
257        let mut rv = Deserializer {
258            vars: Vec::new(),
259            error: None,
260            config,
261        };
262        for (name, value) in std::env::vars_os() {
263            let name = match name.into_string() {
264                Ok(name) => name,
265                Err(name) => {
266                    if strip_prefix(&name.to_string_lossy(), prefix).is_some() {
267                        rv.fail(Error::new(
268                            ErrorKind::Syntax,
269                            format!(
270                                "the name of the environment variable {:?} is not valid unicode",
271                                name
272                            ),
273                        ));
274                    }
275                    continue;
276                }
277            };
278            if strip_prefix(&name, prefix).is_none() {
279                continue;
280            }
281            let value = match value.into_string() {
282                Ok(value) => Value::Text(Cow::Owned(value)),
283                Err(value) => match os_bytes(value) {
284                    Some(bytes) => Value::Bytes(bytes),
285                    None => {
286                        let mut err = Error::new(ErrorKind::Syntax, "value is not valid unicode");
287                        err.set_attachment(EnvVar::new(name.as_str().into()));
288                        rv.fail(err);
289                        continue;
290                    }
291                },
292            };
293            rv.push(name.into(), prefix.len(), value);
294        }
295        rv.finish_vars();
296        rv
297    }
298}
299
300impl<'a> Deserializer<'a> {
301    /// Creates a deserializer for the given variables with a prefix.
302    ///
303    /// The variables are name-value pairs, for instance from
304    /// [`std::env::vars`] or a file.  Values that are given borrowed are
305    /// passed on borrowed.
306    pub fn from_vars<I, K, V>(prefix: &str, vars: I) -> Deserializer<'a>
307    where
308        I: IntoIterator<Item = (K, V)>,
309        K: Into<Cow<'a, str>>,
310        V: Into<Cow<'a, str>>,
311    {
312        Deserializer::from_vars_with_config(prefix, vars, DeserializerConfig::new())
313    }
314
315    /// Creates a deserializer for the given variables with a prefix and
316    /// the given configuration.
317    pub fn from_vars_with_config<I, K, V>(
318        prefix: &str,
319        vars: I,
320        config: DeserializerConfig,
321    ) -> Deserializer<'a>
322    where
323        I: IntoIterator<Item = (K, V)>,
324        K: Into<Cow<'a, str>>,
325        V: Into<Cow<'a, str>>,
326    {
327        let mut rv = Deserializer {
328            vars: Vec::new(),
329            error: None,
330            config,
331        };
332        for (name, value) in vars {
333            let name = name.into();
334            if strip_prefix(&name, prefix).is_some() {
335                rv.push(Arc::from(&*name), prefix.len(), Value::Text(value.into()));
336            }
337        }
338        rv.finish_vars();
339        rv
340    }
341
342    fn push(&mut self, name: Arc<str>, prefix_len: usize, value: Value<'a>) {
343        // the name is only the prefix
344        if name.len() > prefix_len {
345            self.vars.push(Var {
346                name,
347                prefix_len,
348                value,
349            });
350        }
351    }
352
353    fn fail(&mut self, err: Error) {
354        if self.error.is_none() {
355            self.error = Some(err);
356        }
357    }
358
359    /// Sorts the variables, the order of the environment is arbitrary.
360    fn finish_vars(&mut self) {
361        self.vars.sort_by(|a, b| a.name.cmp(&b.name));
362    }
363
364    /// Returns the configuration.
365    pub fn config(&self) -> &DeserializerConfig {
366        &self.config
367    }
368
369    /// Deserializes the variables.
370    ///
371    /// To configure the deserialization (for instance to add layers) use
372    /// [`deserialize_with`](Self::deserialize_with).
373    pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
374        de::Deserializer::deserialize(self)
375    }
376
377    /// Deserializes the variables with a configured driver.
378    ///
379    /// The callback is invoked with the driver before the value is
380    /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s.
381    pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
382    where
383        T: Deserialize<'a>,
384        F: FnOnce(&mut DeserializeDriver<'_, 'a>),
385    {
386        de::Deserializer::deserialize_with(self, setup)
387    }
388
389    /// Feeds the events of the variables into the given driver.
390    ///
391    /// The variables are a map (see the [crate documentation](crate)).  All
392    /// names are checked before the first event is emitted.  The name of
393    /// the variable an event comes from is attached to it and to the errors
394    /// it causes (see [`EnvVar`]).  Values that are given borrowed are passed
395    /// on borrowed.
396    ///
397    /// The context of the configuration is given to the driver (values that
398    /// the context of the driver has take precedence, see
399    /// [`DeserializeDriver::set_default_context`]).
400    pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
401        if !self.config.context.is_empty() {
402            driver.set_default_context(self.config.context.clone());
403        }
404        if let Some(err) = self.error.take() {
405            return Err(err);
406        }
407        let tree = Tree::build(&self.vars, &self.config)?;
408        let state = driver.state_mut();
409        // the last value of repeated keys is used and everything is text
410        // unless the context says otherwise
411        DuplicateKeys::Last.set_default(state);
412        LexicalRules::LENIENT.set_default(state);
413        state.add_error_context::<CurrentVar>();
414        tree.emit(&self.vars, driver)
415    }
416}
417
418impl<'a> de::Deserializer<'a> for Deserializer<'a> {
419    fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
420        Deserializer::drive(self, driver)
421    }
422}
423
424/// Returns the name without the prefix if it starts with the prefix.
425///
426/// On Windows names are not case sensitive, the prefix is matched ignoring
427/// ASCII case.
428fn strip_prefix<'n>(name: &'n str, prefix: &str) -> Option<&'n str> {
429    if cfg!(windows) {
430        let head = name.get(..prefix.len())?;
431        head.eq_ignore_ascii_case(prefix)
432            .then(|| &name[prefix.len()..])
433    } else {
434        name.strip_prefix(prefix)
435    }
436}
437
438/// Returns the bytes of a value that is not valid unicode.
439#[cfg(unix)]
440pub(crate) fn os_bytes(value: OsString) -> Option<Vec<u8>> {
441    use std::os::unix::ffi::OsStringExt;
442    Some(value.into_vec())
443}
444
445#[cfg(not(unix))]
446pub(crate) fn os_bytes(_value: OsString) -> Option<Vec<u8>> {
447    None
448}
449
450/// The name of the variable of the current event.
451///
452/// This is event data which is attached to errors as [`EnvVar`].
453#[derive(Debug, Default, Clone)]
454struct CurrentVar(Option<Arc<str>>);
455
456impl deser_core::ErrorContext for CurrentVar {
457    fn add_context(err: &mut Error, state: &deser_core::State) {
458        if err.attachment::<EnvVar>().is_some() {
459            return;
460        }
461        if let Some(CurrentVar(Some(name))) = state.event::<CurrentVar>() {
462            err.set_attachment(EnvVar::new(name.clone()));
463        }
464    }
465}
466
467/// The key of a node in its parent.
468enum NodeKey {
469    Root,
470    Name(String),
471    /// An index with its text.
472    Index(usize, String),
473}
474
475/// A key and its values.
476struct Node {
477    key: NodeKey,
478    /// The name up to the key, the name of the variable for keys with
479    /// values.
480    name: Option<Arc<str>>,
481    /// The variables that give the key a value.
482    values: Vec<usize>,
483    /// The nested keys in the order in which they appear.
484    children: Vec<usize>,
485}
486
487/// How a node with nested keys is emitted.
488enum Container {
489    Map(Vec<usize>),
490    Seq(Vec<usize>),
491}
492
493/// Identifies the child of a node.
494#[derive(PartialEq, Eq, Hash)]
495enum ChildId {
496    Name(String),
497    Index(usize),
498}
499
500/// The variables as a tree of keys.
501struct Tree {
502    nodes: Vec<Node>,
503}
504
505impl Tree {
506    fn build(vars: &[Var<'_>], config: &DeserializerConfig) -> Result<Tree, Error> {
507        let mut tree = Tree {
508            nodes: vec![Node {
509                key: NodeKey::Root,
510                name: None,
511                values: Vec::new(),
512                children: Vec::new(),
513            }],
514        };
515        let mut lookup = HashMap::new();
516        let mut segments = Vec::new();
517        for (index, var) in vars.iter().enumerate() {
518            segments.clear();
519            split_name(&var.name[var.prefix_len..], config.separator, &mut segments);
520            if segments.len().saturating_sub(1) > config.max_depth {
521                return Err(var_error(
522                    ErrorKind::LimitExceeded,
523                    "name is nested too deeply",
524                    &var.name,
525                ));
526            }
527            let mut node = 0;
528            for (depth, &(start, end)) in segments.iter().enumerate() {
529                let text = &var.name[var.prefix_len + start..var.prefix_len + end];
530                let text = match config.case {
531                    Case::Upper => text.to_ascii_lowercase(),
532                    Case::Preserve => text.to_string(),
533                };
534                let id = match text.parse() {
535                    Ok(index) if depth > 0 && text.bytes().all(|b| b.is_ascii_digit()) => {
536                        ChildId::Index(index)
537                    }
538                    _ => ChildId::Name(text),
539                };
540                let id = (node, id);
541                node = match lookup.get(&id) {
542                    Some(&child) => child,
543                    None => {
544                        let name = if depth + 1 == segments.len() {
545                            var.name.clone()
546                        } else {
547                            Arc::from(&var.name[..var.prefix_len + end])
548                        };
549                        tree.child(&mut lookup, id, name)
550                    }
551                };
552            }
553            tree.nodes[node].values.push(index);
554        }
555        Ok(tree)
556    }
557
558    /// Creates the child of a node.
559    fn child(
560        &mut self,
561        lookup: &mut HashMap<(usize, ChildId), usize>,
562        id: (usize, ChildId),
563        name: Arc<str>,
564    ) -> usize {
565        let parent = id.0;
566        let key = match id.1 {
567            ChildId::Name(ref text) => NodeKey::Name(text.clone()),
568            ChildId::Index(index) => NodeKey::Index(index, index.to_string()),
569        };
570        let child = self.nodes.len();
571        self.nodes.push(Node {
572            key,
573            name: Some(name),
574            values: Vec::new(),
575            children: Vec::new(),
576        });
577        self.nodes[parent].children.push(child);
578        lookup.insert(id, child);
579        child
580    }
581
582    /// Decides how a node with nested keys is emitted.
583    ///
584    /// Indexes that start at 0 and have no gaps are a sequence, everything
585    /// else is a map.
586    fn container(&self, node: &Node) -> Container {
587        let indexes = node
588            .children
589            .iter()
590            .all(|&child| matches!(self.nodes[child].key, NodeKey::Index(..)));
591        if indexes {
592            let mut sorted = node.children.clone();
593            sorted.sort_by_key(|&child| match self.nodes[child].key {
594                NodeKey::Index(index, _) => index,
595                _ => unreachable!(),
596            });
597            let dense = sorted.iter().enumerate().all(|(pos, &child)| {
598                matches!(self.nodes[child].key, NodeKey::Index(index, _) if index == pos)
599            });
600            if dense {
601                return Container::Seq(sorted);
602            }
603        }
604        Container::Map(node.children.clone())
605    }
606
607    /// Returns the shape of a map with children.
608    ///
609    /// Maps are multimaps, the keys of the children are given once per
610    /// variable.
611    fn map_shape(&self, children: &[usize]) -> ContainerShape {
612        let len = children
613            .iter()
614            .map(|&child| self.nodes[child].values.len().max(1))
615            .sum();
616        {
617            let mut shape = ContainerShape::with_len(len);
618            shape.set_multimap(true);
619            shape
620        }
621    }
622
623    /// Emits the events of the tree.
624    fn emit<'a>(
625        &self,
626        vars: &[Var<'a>],
627        driver: &mut DeserializeDriver<'_, 'a>,
628    ) -> Result<(), Error> {
629        struct Frame {
630            children: Vec<usize>,
631            pos: usize,
632            is_map: bool,
633        }
634
635        let root = &self.nodes[0];
636        emit_as(
637            driver,
638            Event::MapStart(self.map_shape(&root.children)),
639            None,
640        )?;
641        let mut stack = vec![Frame {
642            children: root.children.clone(),
643            pos: 0,
644            is_map: true,
645        }];
646
647        while let Some(frame) = stack.last_mut() {
648            let Some(&child) = frame.children.get(frame.pos) else {
649                let event = if frame.is_map {
650                    Event::MapEnd
651                } else {
652                    Event::SeqEnd
653                };
654                stack.pop();
655                emit_as(driver, event, None)?;
656                continue;
657            };
658            frame.pos += 1;
659            let is_map = frame.is_map;
660            let node = &self.nodes[child];
661            if is_map {
662                emit_key(driver, node)?;
663            }
664
665            match (&node.values[..], node.children.is_empty()) {
666                (&[var], true) => emit_value(driver, &vars[var])?,
667                // the key is emitted for every variable (maps are
668                // multimaps)
669                (&[first, ref rest @ ..], true) if is_map => {
670                    emit_value(driver, &vars[first])?;
671                    for &var in rest {
672                        emit_key(driver, node)?;
673                        emit_value(driver, &vars[var])?;
674                    }
675                }
676                // an index of a sequence given more than once
677                (values @ [_, _, ..], true) => {
678                    let policy = DuplicateKeys::of(driver.state());
679                    let var = match policy {
680                        DuplicateKeys::First => values[0],
681                        DuplicateKeys::Error => {
682                            return Err(var_error(
683                                ErrorKind::Syntax,
684                                "more than one variable for the same index",
685                                &vars[values[1]].name,
686                            ));
687                        }
688                        _ => values[values.len() - 1],
689                    };
690                    emit_value(driver, &vars[var])?;
691                }
692                // nodes have values or nested variables
693                ([], true) => unreachable!(),
694                ([], false) => {
695                    let (children, is_map) = match self.container(node) {
696                        Container::Map(children) => (children, true),
697                        Container::Seq(children) => (children, false),
698                    };
699                    let event = if is_map {
700                        Event::MapStart(self.map_shape(&children))
701                    } else {
702                        Event::SeqStart(ContainerShape::with_len(children.len()))
703                    };
704                    emit_as(driver, event, node.name.as_ref())?;
705                    stack.push(Frame {
706                        children,
707                        pos: 0,
708                        is_map,
709                    });
710                }
711                (&[var, ..], false) => {
712                    return Err(var_error(
713                        ErrorKind::Syntax,
714                        "variable has a value and nested variables",
715                        &vars[var].name,
716                    ));
717                }
718            }
719        }
720        Ok(())
721    }
722}
723
724/// Emits the key of a node.
725fn emit_key(driver: &mut DeserializeDriver<'_, '_>, node: &Node) -> Result<(), Error> {
726    let key = match node.key {
727        NodeKey::Name(ref text) | NodeKey::Index(_, ref text) => text,
728        NodeKey::Root => unreachable!(),
729    };
730    emit_as(
731        driver,
732        Atom::Lexical(Text::borrowed(key.as_str())),
733        node.name.as_ref(),
734    )
735}
736
737/// Emits an event with the name of the variable it comes from.
738#[inline]
739fn emit_as<'e, E: Into<Event<'e>>>(
740    driver: &mut DeserializeDriver<'_, '_>,
741    event: E,
742    name: Option<&Arc<str>>,
743) -> Result<(), Error> {
744    if let Some(name) = name {
745        driver.state_mut().event_mut::<CurrentVar>().0 = Some(name.clone());
746    }
747    driver.emit(event)
748}
749
750/// Emits the value of a variable, borrowed if the variable was given
751/// borrowed.
752fn emit_value<'a>(driver: &mut DeserializeDriver<'_, 'a>, var: &Var<'a>) -> Result<(), Error> {
753    driver.state_mut().event_mut::<CurrentVar>().0 = Some(var.name.clone());
754    match var.value {
755        Value::Text(Cow::Borrowed(text)) => {
756            driver.emit_borrowed(Atom::Lexical(Text::borrowed(text)))
757        }
758        Value::Text(Cow::Owned(ref text)) => {
759            driver.emit(Atom::Lexical(Text::borrowed(text.as_str())))
760        }
761        Value::Bytes(ref bytes) => driver.emit(Atom::Bytes(Bytes::borrowed(bytes))),
762    }
763}
764
765/// Splits a name (without the prefix) into the ranges of its segments.
766///
767/// Names that start or end with the separator or have two separators in a
768/// row are not split, they are taken as they are.
769pub(crate) fn split_name(name: &str, separator: &str, segments: &mut Vec<(usize, usize)>) {
770    if !separator.is_empty() {
771        let mut start = 0;
772        for (pos, _) in name.match_indices(separator) {
773            segments.push((start, pos));
774            start = pos + separator.len();
775        }
776        segments.push((start, name.len()));
777        if segments.iter().all(|&(start, end)| start < end) {
778            return;
779        }
780        segments.clear();
781    }
782    segments.push((0, name.len()));
783}
784
785#[cfg(test)]
786fn split(name: &str, separator: &str) -> Vec<String> {
787    let mut segments = Vec::new();
788    split_name(name, separator, &mut segments);
789    segments
790        .into_iter()
791        .map(|(start, end)| name[start..end].to_string())
792        .collect()
793}
794
795#[test]
796fn test_split_name() {
797    assert_eq!(split("PORT", "__"), ["PORT"]);
798    assert_eq!(
799        split("SERVER__MAX_CONNECTIONS", "__"),
800        ["SERVER", "MAX_CONNECTIONS"]
801    );
802    assert_eq!(split("A__0__B", "__"), ["A", "0", "B"]);
803    assert_eq!(split("A_B", "_"), ["A", "B"]);
804    assert_eq!(split("A__B", ""), ["A__B"]);
805    // three underscores are a separator followed by an underscore
806    assert_eq!(split("A___B", "__"), ["A", "_B"]);
807    // malformed names are taken as they are
808    for name in ["__A", "A__", "A____B", "__"] {
809        assert_eq!(split(name, "__"), [name], "{}", name);
810    }
811}
812
813/// Creates an error about a variable.
814#[cold]
815fn var_error(kind: ErrorKind, msg: &'static str, name: &Arc<str>) -> Error {
816    let mut err = Error::new(kind, msg);
817    err.set_attachment(EnvVar::new(name.clone()));
818    err
819}