Skip to main content

triblespace_core/blob/schemas/
longstring.rs

1use crate::blob::Blob;
2use crate::blob::BlobSchema;
3use crate::blob::ToBlob;
4use crate::blob::TryFromBlob;
5use crate::id::ExclusiveId;
6use crate::id::Id;
7use crate::id_hex;
8use crate::macros::entity;
9use crate::metadata;
10use crate::metadata::{ConstDescribe, ConstId};
11use crate::repo::BlobStore;
12use crate::trible::Fragment;
13use crate::value::schemas::hash::Blake3;
14
15use anybytes::view::ViewError;
16use anybytes::View;
17
18/// Arbitrary-length UTF-8 text stored as a blob.
19///
20/// Use for text that does not fit in the 32-byte [`ShortString`](crate::value::schemas::shortstring::ShortString)
21/// value boundary — documents, prompts, JSON payloads, logs, etc.
22/// Reference it from tribles via a [`Handle<Blake3, LongString>`](crate::value::schemas::hash::Handle).
23pub struct LongString {}
24
25impl BlobSchema for LongString {}
26
27impl ConstId for LongString {
28    const ID: Id = id_hex!("8B173C65B7DB601A11E8A190BD774A79");
29}
30
31impl ConstDescribe for LongString {
32    fn describe<B>(blobs: &mut B) -> Result<Fragment, B::PutError>
33    where
34        B: BlobStore<Blake3>,
35    {
36        let id = Self::ID;
37        let description = blobs.put(
38            "Arbitrary-length UTF-8 text stored as a blob. This is the default choice for any textual payload that does not fit in 32 bytes, such as documents, prompts, JSON, or logs.\n\nUse ShortString when you need a fixed-width value embedded directly in tribles, want to derive attributes from the bytes, or need predictable ordering inside value indices. LongString is for payloads where size can vary or exceed the value boundary.",
39        )?;
40        Ok(entity! {
41            ExclusiveId::force_ref(&id) @
42                metadata::name: blobs.put("longstring")?,
43                metadata::description: description,
44                metadata::tag: metadata::KIND_BLOB_SCHEMA,
45        })
46    }
47}
48
49impl TryFromBlob<LongString> for View<str> {
50    type Error = ViewError;
51
52    fn try_from_blob(b: Blob<LongString>) -> Result<Self, Self::Error> {
53        b.bytes.view()
54    }
55}
56
57impl ToBlob<LongString> for View<str> {
58    fn to_blob(self) -> Blob<LongString> {
59        Blob::new(self.bytes())
60    }
61}
62
63impl ToBlob<LongString> for &'static str {
64    fn to_blob(self) -> Blob<LongString> {
65        Blob::new(self.into())
66    }
67}
68
69impl ToBlob<LongString> for String {
70    fn to_blob(self) -> Blob<LongString> {
71        Blob::new(self.into())
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use anybytes::Bytes;
78    use anybytes::View;
79
80    use crate::blob::schemas::longstring::LongString;
81    use crate::blob::ToBlob;
82    use crate::value::schemas::hash::Blake3;
83    use crate::value::schemas::hash::Handle;
84    use crate::value::Value;
85
86    #[test]
87    fn string_handle() {
88        let s: View<str> = Bytes::from(String::from("hello world!")).view().unwrap();
89        let h: Value<Handle<Blake3, LongString>> = s.clone().to_blob().get_handle();
90        let h2: Value<Handle<Blake3, LongString>> = s.clone().to_blob().get_handle();
91
92        assert!(h == h2);
93    }
94}