Skip to main content

cadmpeg_ir/
unknown.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Retained source records without a typed IR interpretation.
3#![deny(clippy::disallowed_methods)]
4
5use crate::ids::UnknownId;
6use crate::native::NativeRecord;
7use base64::{engine::general_purpose::STANDARD, Engine as _};
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use serde_json::{Map, Number, Value};
11
12/// A format-specific product record.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
14pub struct NativeUnknownRecord {
15    /// Arena id.
16    pub id: UnknownId,
17    /// Related entity IDs from any document arena.
18    #[serde(default, skip_serializing_if = "Vec::is_empty")]
19    pub links: Vec<String>,
20}
21
22impl From<&UnknownRecord> for NativeUnknownRecord {
23    fn from(record: &UnknownRecord) -> Self {
24        Self {
25            id: record.id.clone(),
26            links: record.links.clone(),
27        }
28    }
29}
30
31/// A recognized source record represented by location, digest, links, and
32/// optional retained bytes.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
34pub struct UnknownRecord {
35    /// Arena id.
36    pub id: UnknownId,
37    /// Byte offset of the record within its source stream.
38    pub offset: u64,
39    /// Byte length of the record's span.
40    pub byte_len: u64,
41    /// Lowercase hex SHA-256 of the record bytes, for integrity and dedup.
42    pub sha256: String,
43    /// Preserved record bytes, when retained by the decoder.
44    #[serde(
45        default,
46        skip_serializing_if = "Option::is_none",
47        with = "crate::bytes::option"
48    )]
49    #[schemars(with = "Option<String>")]
50    pub data: Option<Vec<u8>>,
51    /// Related entity IDs from any document arena.
52    #[serde(default, skip_serializing_if = "Vec::is_empty")]
53    pub links: Vec<String>,
54}
55
56impl UnknownRecord {
57    pub(crate) fn into_native_record(self) -> NativeRecord {
58        let mut fields = Map::new();
59        fields.insert("offset".into(), Value::Number(Number::from(self.offset)));
60        fields.insert(
61            "byte_len".into(),
62            Value::Number(Number::from(self.byte_len)),
63        );
64        fields.insert("sha256".into(), Value::String(self.sha256));
65        if let Some(data) = self.data {
66            fields.insert("data".into(), Value::String(STANDARD.encode(data)));
67        }
68        if !self.links.is_empty() {
69            fields.insert(
70                "links".into(),
71                Value::Array(self.links.into_iter().map(Value::String).collect()),
72            );
73        }
74        NativeRecord {
75            id: self.id.0,
76            fields,
77        }
78    }
79}