1use strict_encoding::{StrictDeserialize, StrictSerialize, TypeName};
25use ultrasonic::{Contract, ContractId};
26
27use crate::sigs::ContentSigs;
28use crate::{Api, Schema, LIB_NAME_SONIC};
29
30#[derive(Clone, Eq, PartialEq, Debug)]
32#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
33#[strict_type(lib = LIB_NAME_SONIC)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
35pub struct Articles {
36 #[cfg_attr(feature = "serde", serde(flatten))]
37 pub schema: Schema,
38 pub contract_sigs: ContentSigs,
39 pub contract: Contract,
40}
41
42impl StrictSerialize for Articles {}
43impl StrictDeserialize for Articles {}
44
45impl Articles {
46 pub fn contract_id(&self) -> ContractId { self.contract.contract_id() }
47
48 pub fn api(&self, name: &TypeName) -> &Api { self.schema.api(name) }
49
50 pub fn merge(&mut self, other: Self) -> Result<bool, MergeError> {
51 if self.contract_id() != other.contract_id() {
52 return Err(MergeError::ContractMismatch);
53 }
54
55 self.schema.merge(other.schema)?;
56 self.contract_sigs.merge(other.contract_sigs);
57
58 Ok(true)
59 }
60}
61
62#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
63#[display(doc_comments)]
64pub enum MergeError {
65 ContractMismatch,
67
68 CodexMismatch,
70}
71
72#[cfg(feature = "std")]
73mod _fs {
74 use std::path::Path;
75
76 use strict_encoding::{DeserializeError, SerializeError, StrictDeserialize, StrictSerialize};
77
78 use super::Articles;
79
80 impl Articles {
81 pub fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError> {
82 Self::strict_deserialize_from_file::<{ usize::MAX }>(path)
83 }
84
85 pub fn save(&self, path: impl AsRef<Path>) -> Result<(), SerializeError> {
86 self.strict_serialize_to_file::<{ usize::MAX }>(path)
87 }
88 }
89}