Skip to main content

sark_json/segment/document/
value.rs

1use o3::buffer::storage;
2
3use crate::{
4    Error, Token,
5    segment::{
6        Cursor, Stored, ValueKind,
7        input::{Input, Split},
8        state,
9    },
10};
11
12/// One present field borrowed together with its unchanged backing input.
13/// Its validated kind and retained range survive every projection through this borrow.
14pub struct Value<'a, 'd> {
15    input: &'a Input<'d>,
16    value: &'a state::Value,
17}
18
19impl<'a, 'd> Value<'a, 'd> {
20    pub(super) fn new(input: &'a Input<'d>, value: &'a state::Value) -> Self {
21        Self { input, value }
22    }
23
24    pub fn is_null(&self) -> bool {
25        matches!(self.value.kind, ValueKind::Null)
26    }
27
28    pub fn u64(&self) -> crate::Result<u64> {
29        match self.value.kind {
30            ValueKind::Unsigned(value) => Ok(value),
31            _ => Err(Error::Invalid),
32        }
33    }
34
35    pub fn i64(&self) -> crate::Result<i64> {
36        self.value.kind.i64()
37    }
38
39    pub fn boolean(&self) -> crate::Result<bool> {
40        match self.value.kind {
41            ValueKind::True => Ok(true),
42            ValueKind::False => Ok(false),
43            _ => Err(Error::Invalid),
44        }
45    }
46
47    pub fn frame(&self) -> crate::Result<crate::Text<storage::Shared>> {
48        let shared = match self.value.kind {
49            ValueKind::String { escapes: 0 } => self.materialize(1, 1),
50            ValueKind::String { escapes: 1.. } => match &self.value.stored {
51                Stored::Decoded(decoded) => decoded.try_clone().map_err(Error::Retain),
52                _ => Err(Error::Invalid),
53            },
54            _ => Err(Error::Invalid),
55        };
56        shared.map(crate::Text::admitted)
57    }
58
59    pub fn plain(&self) -> crate::Result<crate::Plain<storage::Shared>> {
60        let shared = match self.value.kind {
61            ValueKind::String { escapes: 0 } => self.materialize(1, 1),
62            _ => Err(Error::Invalid),
63        };
64        shared.map(crate::Plain::admitted)
65    }
66
67    pub fn raw(&self) -> crate::Result<crate::Raw<storage::Shared>> {
68        self.materialize(0, 0).map(crate::Raw::admitted)
69    }
70
71    pub fn inline_plain<const N: usize>(&self) -> crate::Result<crate::Plain<Token<N>>> {
72        let token = match self.value.kind {
73            ValueKind::String { escapes: 0 } => self.inline(1, 1),
74            _ => Err(Error::Invalid),
75        };
76        token.map(crate::Plain::admitted)
77    }
78
79    pub fn inline_raw<const N: usize>(&self) -> crate::Result<crate::Raw<Token<N>>> {
80        self.inline(0, 0).map(crate::Raw::admitted)
81    }
82
83    pub(super) fn split(&self) -> crate::Result<Split<'d>> {
84        let Stored::Segments(range) = &self.value.stored else {
85            return Err(Error::Invalid);
86        };
87        if !matches!(self.value.kind, ValueKind::Compound) {
88            return Err(Error::Invalid);
89        }
90        Split::new(self.input, range.clone())
91    }
92
93    fn materialize(&self, head: usize, tail: usize) -> crate::Result<storage::Shared> {
94        match &self.value.stored {
95            Stored::Bytes(range) | Stored::Frame(range) | Stored::Segments(range) => {
96                self.input.project(range.start + head..range.end - tail)
97            }
98            Stored::Copied(shared) => shared
99                .try_get(head..shared.len() - tail)
100                .map_err(Error::Retain)?
101                .ok_or(Error::Invalid),
102            _ => Err(Error::Invalid),
103        }
104    }
105
106    fn inline<const N: usize>(&self, head: usize, tail: usize) -> crate::Result<Token<N>> {
107        const { assert!(N <= u8::MAX as usize) }
108        match &self.value.stored {
109            Stored::Bytes(range) | Stored::Frame(range) | Stored::Segments(range) => {
110                let mut token = Token::new();
111                let start = range.start + head;
112                let end = range.end - tail;
113                let mut cursor = Cursor::at(self.input, start).ok_or(Error::Invalid)?;
114                while cursor.absolute < end {
115                    let (byte, advance) = cursor.read(self.input).ok_or(Error::Invalid)?;
116                    token.push(byte)?;
117                    cursor.advance(advance);
118                }
119                Ok(token)
120            }
121            Stored::Copied(shared) => {
122                let mut token = Token::new();
123                let end = shared.len() - tail;
124                for byte in shared.as_slice().get(head..end).ok_or(Error::Invalid)? {
125                    token.push(*byte)?;
126                }
127                Ok(token)
128            }
129            _ => Err(Error::Invalid),
130        }
131    }
132}