ergotree_ir/ergo_tree/
tree_header.rs1use derive_more::From;
4use thiserror::Error;
5
6use crate::serialization::sigma_byte_reader::SigmaByteRead;
7use crate::serialization::sigma_byte_writer::SigmaByteWrite;
8
9#[derive(PartialEq, Eq, Debug, Clone)]
27pub struct ErgoTreeHeader {
28 version: ErgoTreeVersion,
29 is_constant_segregation: bool,
30 has_size: bool,
31}
32
33impl ErgoTreeHeader {
34 pub fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> Result<(), std::io::Error> {
36 w.put_u8(self.serialized())
37 }
38 pub fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, ErgoTreeHeaderError> {
40 let header_byte = r
41 .get_u8()
42 .map_err(|e| ErgoTreeHeaderError::IoError(e.to_string()))?;
43
44 ErgoTreeHeader::new(header_byte)
45 }
46}
47
48impl ErgoTreeHeader {
49 const CONSTANT_SEGREGATION_FLAG: u8 = 0b0001_0000;
50 const HAS_SIZE_FLAG: u8 = 0b0000_1000;
51
52 pub fn new(header_byte: u8) -> Result<Self, ErgoTreeHeaderError> {
54 let version = ErgoTreeVersion::parse_version(header_byte)?;
55 let has_size = header_byte & Self::HAS_SIZE_FLAG != 0;
56 let is_constant_segregation = header_byte & Self::CONSTANT_SEGREGATION_FLAG != 0;
57 Ok(ErgoTreeHeader {
58 version,
59 is_constant_segregation,
60 has_size,
61 })
62 }
63
64 pub fn serialized(&self) -> u8 {
66 let mut header_byte: u8 = self.version.0;
67 if self.is_constant_segregation {
68 header_byte |= Self::CONSTANT_SEGREGATION_FLAG;
69 }
70 if self.has_size {
71 header_byte |= Self::HAS_SIZE_FLAG;
72 }
73 header_byte
74 }
75
76 pub fn v0(constant_segregation: bool) -> Self {
78 ErgoTreeHeader {
79 version: ErgoTreeVersion::V0,
80 is_constant_segregation: constant_segregation,
81 has_size: false,
82 }
83 }
84
85 pub fn v1(constant_segregation: bool) -> Self {
87 ErgoTreeHeader {
88 version: ErgoTreeVersion::V1,
89 is_constant_segregation: constant_segregation,
90 has_size: true,
91 }
92 }
93
94 pub fn is_constant_segregation(&self) -> bool {
96 self.is_constant_segregation
97 }
98
99 pub fn has_size(&self) -> bool {
101 self.has_size
102 }
103
104 pub fn version(&self) -> &ErgoTreeVersion {
106 &self.version
107 }
108}
109
110#[derive(Error, PartialEq, Eq, Debug, Clone, From)]
112pub enum ErgoTreeHeaderError {
113 #[error("Invalid version: {0}")]
115 VersionError(ErgoTreeVersionError),
116 #[error("IO error: {0}")]
118 IoError(String),
119}
120
121#[derive(PartialEq, Eq, Debug, Clone)]
123pub struct ErgoTreeVersion(u8);
124
125impl ErgoTreeVersion {
126 pub const VERSION_MASK: u8 = 0x07;
128 pub const V0: Self = ErgoTreeVersion(0);
130 pub const V1: Self = ErgoTreeVersion(1);
132
133 pub fn parse_version(header_byte: u8) -> Result<Self, ErgoTreeVersionError> {
135 let version = header_byte & ErgoTreeVersion::VERSION_MASK;
136 if version <= 1 {
137 Ok(ErgoTreeVersion(version))
138 } else {
139 Err(ErgoTreeVersionError::InvalidVersion(version))
140 }
141 }
142}
143
144#[derive(Error, PartialEq, Eq, Debug, Clone, From)]
146pub enum ErgoTreeVersionError {
147 #[error("Invalid version: {0}")]
149 InvalidVersion(u8),
150}