summaryrefslogtreecommitdiff
path: root/systems
diff options
context:
space:
mode:
Diffstat (limited to 'systems')
-rw-r--r--systems/sheet/Cargo.toml2
-rw-r--r--systems/sheet/macros/src/lib.rs41
-rw-r--r--systems/sheet/src/mapping.rs33
-rw-r--r--systems/sheet/src/sheet.rs184
-rw-r--r--systems/sheet/src/sheet/current.rs5
-rw-r--r--systems/sheet/src/sheet/error.rs19
-rw-r--r--systems/sheet/src/sheet/reader.rs19
-rw-r--r--systems/sheet/src/sheet/v1.rs6
-rw-r--r--systems/sheet/src/sheet/v1/reader.rs9
-rw-r--r--systems/sheet/src/sheet/v1/test.rs2
-rw-r--r--systems/sheet/src/sheet/v1/writer.rs8
-rw-r--r--systems/sheet/src/sheet/writer.rs8
12 files changed, 272 insertions, 64 deletions
diff --git a/systems/sheet/Cargo.toml b/systems/sheet/Cargo.toml
index 074f511..657c567 100644
--- a/systems/sheet/Cargo.toml
+++ b/systems/sheet/Cargo.toml
@@ -13,7 +13,7 @@ asset_system = { path = "../_asset" }
tokio = { version = "1.48", features = ["full"] }
thiserror = "1.0.69"
-just_fmt = "0.1"
+just_fmt = "0.1.2"
memmap2 = "0.9"
sha2 = "0.10.8"
diff --git a/systems/sheet/macros/src/lib.rs b/systems/sheet/macros/src/lib.rs
index b485a82..c06f25e 100644
--- a/systems/sheet/macros/src/lib.rs
+++ b/systems/sheet/macros/src/lib.rs
@@ -3,8 +3,6 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use syn::parse_str;
-const INDEX_SOURCE_BUF: &str =
- "just_enough_vcs::system::sheet_system::index_source::IndexSourceBuf";
const INDEX_SOURCE: &str = "just_enough_vcs::system::sheet_system::index_source::IndexSource";
const LOCAL_MAPPING_PATH: &str = "just_enough_vcs::system::sheet_system::mapping::LocalMapping";
@@ -38,7 +36,7 @@ fn parse_sheet_path(input: &str) -> Result<(String, Vec<String>), String> {
}
/// Parse strings in the format "id/ver"
-fn parse_id_version(input: &str) -> Result<(String, String), String> {
+fn parse_id_version(input: &str) -> Result<(u32, u16), String> {
let parts: Vec<&str> = input.split('/').collect();
if parts.len() != 2 {
return Err(format!(
@@ -47,16 +45,23 @@ fn parse_id_version(input: &str) -> Result<(String, String), String> {
));
}
- let id = parts[0].trim().to_string();
- let ver = parts[1].trim().to_string();
+ let id_str = parts[0].trim();
+ let ver_str = parts[1].trim();
- if id.is_empty() {
+ if id_str.is_empty() {
return Err("ID cannot be empty".to_string());
}
- if ver.is_empty() {
+ if ver_str.is_empty() {
return Err("Version cannot be empty".to_string());
}
+ let id = id_str
+ .parse::<u32>()
+ .map_err(|e| format!("Failed to parse id as u32: {}", e))?;
+ let ver = ver_str
+ .parse::<u16>()
+ .map_err(|e| format!("Failed to parse version as u16: {}", e))?;
+
Ok((id, ver))
}
@@ -121,14 +126,14 @@ pub fn mapping_buf(input: TokenStream) -> TokenStream {
let mapping_buf_path: syn::Path =
parse_str(MAPPING_BUF_PATH).expect("Failed to parse MAPPING_BUF_PATH");
- let index_source_buf_path: syn::Path =
- parse_str(INDEX_SOURCE_BUF).expect("Failed to parse INDEX_SOURCE_BUF");
+ let index_source_path: syn::Path =
+ parse_str(INDEX_SOURCE).expect("Failed to parse INDEX_SOURCE");
let expanded = quote! {
#mapping_buf_path::new(
#sheet.to_string(),
#path_vec_tokens,
- #index_source_buf_path::new(#id.to_string(), #ver.to_string())
+ #index_source_path::new(#id, #ver)
)
};
@@ -198,9 +203,9 @@ pub fn mapping(input: TokenStream) -> TokenStream {
}
enum LocalMappingParts {
- Latest(String, String, String),
- Version(String, String, String),
- WithRef(String, String, String, String),
+ Latest(String, u32, u16),
+ Version(String, u32, u16),
+ WithRef(String, u32, u16, String),
}
impl LocalMappingParts {
@@ -317,8 +322,8 @@ pub fn local_mapping(input: TokenStream) -> TokenStream {
parse_str(LOCAL_MAPPING_PATH).expect("Failed to parse LOCAL_MAPPING_PATH");
let local_mapping_forward_path: syn::Path =
parse_str(LOCAL_MAPPING_FORWARD_PATH).expect("Failed to parse LOCAL_MAPPING_FORWARD_PATH");
- let index_source_buf_path: syn::Path =
- parse_str(INDEX_SOURCE_BUF).expect("Failed to parse INDEX_SOURCE_BUF");
+ let index_source_path: syn::Path =
+ parse_str(INDEX_SOURCE).expect("Failed to parse INDEX_SOURCE");
match parts {
LocalMappingParts::Latest(path_str, id, ver) => {
@@ -328,7 +333,7 @@ pub fn local_mapping(input: TokenStream) -> TokenStream {
let expanded = quote! {
#local_mapping_path::new(
#path_vec_tokens,
- #index_source_buf_path::new(#id.to_string(), #ver.to_string()),
+ #index_source_path::new(#id, #ver),
#local_mapping_forward_path::Latest
)
};
@@ -342,7 +347,7 @@ pub fn local_mapping(input: TokenStream) -> TokenStream {
let expanded = quote! {
#local_mapping_path::new(
#path_vec_tokens,
- #index_source_buf_path::new(#id.to_string(), #ver.to_string()),
+ #index_source_path::new(#id, #ver),
#local_mapping_forward_path::Version {
version_name: #ver.to_string()
}
@@ -358,7 +363,7 @@ pub fn local_mapping(input: TokenStream) -> TokenStream {
let expanded = quote! {
#local_mapping_path::new(
#path_vec_tokens,
- #index_source_buf_path::new(#id.to_string(), #ver.to_string()),
+ #index_source_path::new(#id, #ver),
#local_mapping_forward_path::Ref {
sheet_name: #ref_name.to_string()
}
diff --git a/systems/sheet/src/mapping.rs b/systems/sheet/src/mapping.rs
index 0a72a69..1743534 100644
--- a/systems/sheet/src/mapping.rs
+++ b/systems/sheet/src/mapping.rs
@@ -507,6 +507,11 @@ impl LocalMapping {
pub fn set_forward(&mut self, forward: &LocalMappingForward) {
self.forward = forward.clone();
}
+
+ /// Replace the forward direction of the current LocalMapping
+ pub fn replace_forward(&mut self, forward: LocalMappingForward) {
+ self.forward = forward;
+ }
}
#[inline(always)]
@@ -591,3 +596,31 @@ impl std::borrow::Borrow<Vec<String>> for MappingBuf {
&self.val
}
}
+
+/// Convert a string into a Node suitable for Mapping
+///
+/// # Examples
+///
+/// ```
+/// # use sheet_system::mapping::node;
+/// assert_eq!(
+/// node("./home/path1/"),
+/// vec!["home".to_string(), "path1".to_string(), "".to_string()]
+/// );
+/// assert_eq!(
+/// node("./home/path2"),
+/// vec!["home".to_string(), "path2".to_string()]
+/// );
+/// assert_eq!(
+/// node(".\\home\\path3\\"),
+/// vec!["home".to_string(), "path3".to_string(), "".to_string()]
+/// );
+/// assert_eq!(
+/// node("home/path4"),
+/// vec!["home".to_string(), "path4".to_string()]
+/// );
+/// ```
+pub fn node(str: impl Into<String>) -> Vec<String> {
+ let str = just_fmt::fmt_path::fmt_path_str(str).unwrap_or_default();
+ str.split("/").into_iter().map(|f| f.to_string()).collect()
+}
diff --git a/systems/sheet/src/sheet.rs b/systems/sheet/src/sheet.rs
index 68c4c78..44c2878 100644
--- a/systems/sheet/src/sheet.rs
+++ b/systems/sheet/src/sheet.rs
@@ -1,6 +1,7 @@
use std::{
collections::HashSet,
fs::File,
+ mem::replace,
path::{Path, PathBuf},
};
@@ -11,19 +12,18 @@ use crate::{
index_source::IndexSource,
mapping::{LocalMapping, LocalMappingForward, Mapping, MappingBuf},
sheet::{
- error::{ReadSheetDataError, SheetEditError},
+ error::{ReadSheetDataError, SheetApplyError, SheetEditError},
reader::{read_mapping, read_sheet_data},
writer::convert_sheet_data_to_bytes,
},
};
-pub mod constants;
pub mod error;
pub mod reader;
pub mod writer;
-#[cfg(test)]
-pub mod test;
+// Format
+pub mod v1;
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Sheet {
@@ -59,6 +59,21 @@ pub struct SheetDataMmap {
pub struct SheetEdit {
/// Edit history
list: Vec<SheetEditItem>,
+
+ /// List of lost nodes
+ lost_nodes: HashSet<Vec<String>>,
+
+ /// List of filled nodes
+ filled_nodes: HashSet<Vec<String>>,
+}
+
+impl SheetEdit {
+ /// Clear current SheetEdit information
+ pub fn clear(&mut self) {
+ self.list.clear();
+ self.lost_nodes.clear();
+ self.filled_nodes.clear();
+ }
}
#[derive(Default, Debug, Clone, PartialEq)]
@@ -119,7 +134,7 @@ impl std::fmt::Display for SheetEditItem {
)
}
SheetEditItem::EraseMapping { node } => {
- write!(f, "Earse \"{}\"", display_node_helper(node),)
+ write!(f, "erase \"{}\"", display_node_helper(node),)
}
SheetEditItem::InsertMapping { mapping } => {
write!(f, "Insert {}", mapping.to_string())
@@ -207,7 +222,7 @@ impl SheetData {
Sheet {
name: sheet_name.into(),
data: self,
- edit: SheetEdit { list: Vec::new() },
+ edit: SheetEdit::default(),
}
}
}
@@ -244,8 +259,16 @@ impl Sheet {
self.data
}
- /// Check if a mapping exists in the Sheet
+ /// Check if a mapping exists in this sheet (including unapplied edits)
+ /// The difference from `contains_mapping_actual` is:
+ /// This method will consider edit operations that have not yet been `apply()`-ed
pub fn contains_mapping(&self, value: &Vec<String>) -> bool {
+ self.data.contains_mapping(value) && !self.edit.lost_nodes.contains(value)
+ || self.edit.filled_nodes.contains(value)
+ }
+
+ /// Check if a mapping actually exists in this sheet
+ pub fn contains_mapping_actual(&self, value: &Vec<String>) -> bool {
self.data.contains_mapping(value)
}
@@ -262,20 +285,30 @@ impl Sheet {
}
}
- /// Insert mapping modification
- pub fn insert_mapping(
+ /// Insert mapping move
+ pub fn move_mapping(
&mut self,
- mapping: impl Into<LocalMapping>,
+ from_node: Vec<String>,
+ to_node: Vec<String>,
) -> Result<(), SheetEditError> {
- self.edit.list.push(SheetEditItem::InsertMapping {
- mapping: mapping.into(),
- });
- Ok(())
- }
+ if !self.contains_mapping(&from_node) {
+ return Err(SheetEditError::NodeNotFound(from_node.join("/")));
+ }
+
+ if self.contains_mapping(&to_node) {
+ return Err(SheetEditError::NodeAlreadyExist(to_node.join("/")));
+ }
+
+ self.edit.filled_nodes.remove(&from_node);
+ self.edit.lost_nodes.remove(&to_node);
+
+ self.edit.lost_nodes.insert(from_node.clone());
+ self.edit.filled_nodes.insert(to_node.clone());
+
+ self.edit
+ .list
+ .push(SheetEditItem::Move { from_node, to_node });
- /// Insert mapping erasure
- pub fn earse_mapping(&mut self, node: Vec<String>) -> Result<(), SheetEditError> {
- self.edit.list.push(SheetEditItem::EraseMapping { node });
Ok(())
}
@@ -285,19 +318,49 @@ impl Sheet {
node_a: Vec<String>,
node_b: Vec<String>,
) -> Result<(), SheetEditError> {
+ if !self.contains_mapping(&node_a) {
+ return Err(SheetEditError::NodeNotFound(node_a.join("/")));
+ }
+
+ if !self.contains_mapping(&node_b) {
+ return Err(SheetEditError::NodeNotFound(node_b.join("/")));
+ }
+
self.edit.list.push(SheetEditItem::Swap { node_a, node_b });
Ok(())
}
- /// Insert mapping move
- pub fn move_mapping(
+ /// Insert mapping erasure
+ pub fn erase_mapping(&mut self, node: Vec<String>) -> Result<(), SheetEditError> {
+ if !self.contains_mapping(&node) {
+ return Err(SheetEditError::NodeNotFound(node.join("/")));
+ }
+
+ self.edit.filled_nodes.remove(&node);
+ self.edit.lost_nodes.insert(node.clone());
+
+ self.edit.list.push(SheetEditItem::EraseMapping { node });
+ Ok(())
+ }
+
+ /// Insert mapping modification
+ pub fn insert_mapping(
&mut self,
- from_node: Vec<String>,
- to_node: Vec<String>,
+ mapping: impl Into<LocalMapping>,
) -> Result<(), SheetEditError> {
+ let mapping = mapping.into();
+ let node = mapping.value();
+
+ if self.contains_mapping(node) {
+ return Err(SheetEditError::NodeAlreadyExist(node.join("/")));
+ }
+
+ self.edit.lost_nodes.remove(node);
+ self.edit.filled_nodes.insert(node.clone());
+
self.edit
.list
- .push(SheetEditItem::Move { from_node, to_node });
+ .push(SheetEditItem::InsertMapping { mapping });
Ok(())
}
@@ -307,6 +370,10 @@ impl Sheet {
node: Vec<String>,
source: IndexSource,
) -> Result<(), SheetEditError> {
+ if !self.contains_mapping(&node) {
+ return Err(SheetEditError::NodeNotFound(node.join("/")));
+ }
+
self.edit
.list
.push(SheetEditItem::ReplaceSource { node, source });
@@ -319,6 +386,10 @@ impl Sheet {
node: Vec<String>,
forward: LocalMappingForward,
) -> Result<(), SheetEditError> {
+ if !self.contains_mapping(&node) {
+ return Err(SheetEditError::NodeNotFound(node.join("/")));
+ }
+
self.edit
.list
.push(SheetEditItem::UpdateForward { node, forward });
@@ -326,13 +397,70 @@ impl Sheet {
}
/// Apply changes
- pub fn apply(&mut self) {
- // Logic for applying changes
- todo!();
+ pub fn apply(&mut self) -> Result<(), SheetApplyError> {
+ let items = replace(&mut self.edit.list, Vec::new());
+ for item in items {
+ match item {
+ SheetEditItem::DoNothing => continue,
+ SheetEditItem::Move { from_node, to_node } => {
+ let mut moved =
+ self.data.mappings.take(&from_node).ok_or_else(|| {
+ SheetApplyError::UnexpectedNotFound(from_node.join("/"))
+ })?;
+ moved.set_value(to_node);
+ self.data.mappings.insert(moved);
+ }
+ SheetEditItem::Swap { node_a, node_b } => {
+ let mut a = self
+ .data
+ .mappings
+ .take(&node_a)
+ .ok_or_else(|| SheetApplyError::UnexpectedNotFound(node_a.join("/")))?;
+ let mut b = self
+ .data
+ .mappings
+ .take(&node_b)
+ .ok_or_else(|| SheetApplyError::UnexpectedNotFound(node_b.join("/")))?;
+ let val_a = a.value().clone();
+ let val_b = b.value().clone();
+ a.set_value(val_b);
+ b.set_value(val_a);
+ }
+ SheetEditItem::EraseMapping { node } => {
+ if !self.data.mappings.remove(&node) {
+ return Err(SheetApplyError::UnexpectedNotFound(node.join("/")));
+ }
+ }
+ SheetEditItem::InsertMapping { mapping } => {
+ let node = mapping.value().clone();
+ if !self.data.mappings.insert(mapping) {
+ return Err(SheetApplyError::UnexpectedAlreadyExist(node.join("/")));
+ }
+ }
+ SheetEditItem::ReplaceSource { node, source } => {
+ let mut target = self
+ .data
+ .mappings
+ .take(&node)
+ .ok_or_else(|| SheetApplyError::UnexpectedNotFound(node.join("/")))?;
+ target.replace_source(source);
+ self.data.mappings.insert(target);
+ }
+ SheetEditItem::UpdateForward { node, forward } => {
+ let mut target = self
+ .data
+ .mappings
+ .take(&node)
+ .ok_or_else(|| SheetApplyError::UnexpectedNotFound(node.join("/")))?;
+ target.replace_forward(forward);
+ self.data.mappings.insert(target);
+ }
+ }
+ }
// Clear the edit list
- #[allow(unreachable_code)] // Note: Remove after todo!() is completed
- self.edit.list.clear();
+ self.edit.clear();
+ Ok(())
}
}
diff --git a/systems/sheet/src/sheet/current.rs b/systems/sheet/src/sheet/current.rs
new file mode 100644
index 0000000..0efc993
--- /dev/null
+++ b/systems/sheet/src/sheet/current.rs
@@ -0,0 +1,5 @@
+#[allow(unused_imports)]
+use crate::sheet::v1::reader;
+
+#[allow(unused_imports)]
+use crate::sheet::v1::writer;
diff --git a/systems/sheet/src/sheet/error.rs b/systems/sheet/src/sheet/error.rs
index 79f7214..3e5661a 100644
--- a/systems/sheet/src/sheet/error.rs
+++ b/systems/sheet/src/sheet/error.rs
@@ -1,12 +1,19 @@
-use crate::sheet::SheetEditItem;
-
#[derive(Debug, thiserror::Error)]
pub enum SheetEditError {
- #[error("Edit `{0}` Failed: Node already exists: `{1}`")]
- NodeAlreadyExist(SheetEditItem, String),
+ #[error("Edit Failed: Node already exists: `{0}`")]
+ NodeAlreadyExist(String),
+
+ #[error("Edit Failed: Node not found: `{0}`")]
+ NodeNotFound(String),
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum SheetApplyError {
+ #[error("Node already exists: `{0}` (Unexpected)")]
+ UnexpectedAlreadyExist(String),
- #[error("Edit `{0}` Failed: Node not found: `{1}`")]
- NodeNotFound(SheetEditItem, String),
+ #[error("Unexpected error: Node not found: `{0}` (Unexpected)")]
+ UnexpectedNotFound(String),
}
#[derive(Debug, thiserror::Error)]
diff --git a/systems/sheet/src/sheet/reader.rs b/systems/sheet/src/sheet/reader.rs
new file mode 100644
index 0000000..87347bb
--- /dev/null
+++ b/systems/sheet/src/sheet/reader.rs
@@ -0,0 +1,19 @@
+use crate::{
+ mapping::{LocalMappingForward, Mapping},
+ sheet::{SheetData, error::ReadSheetDataError},
+};
+
+include!("current.rs");
+
+/// Reconstruct complete SheetData from full sheet data
+pub fn read_sheet_data(full_sheet_data: &[u8]) -> Result<SheetData, ReadSheetDataError> {
+ reader::read_sheet_data(full_sheet_data)
+}
+
+/// Read mapping information for a specific node from complete sheet data
+pub fn read_mapping<'a>(
+ full_sheet_data: &'a [u8],
+ node: &[&str],
+) -> Result<Option<(Mapping<'a>, LocalMappingForward)>, ReadSheetDataError> {
+ reader::read_mapping(full_sheet_data, node)
+}
diff --git a/systems/sheet/src/sheet/v1.rs b/systems/sheet/src/sheet/v1.rs
new file mode 100644
index 0000000..c32f92c
--- /dev/null
+++ b/systems/sheet/src/sheet/v1.rs
@@ -0,0 +1,6 @@
+pub mod constants;
+pub mod reader;
+pub mod writer;
+
+#[cfg(test)]
+pub mod test;
diff --git a/systems/sheet/src/sheet/v1/reader.rs b/systems/sheet/src/sheet/v1/reader.rs
index d86b097..e23e91b 100644
--- a/systems/sheet/src/sheet/v1/reader.rs
+++ b/systems/sheet/src/sheet/v1/reader.rs
@@ -3,16 +3,16 @@ use crate::{
mapping::{LocalMapping, LocalMappingForward, Mapping},
sheet::{
SheetData,
- constants::{
+ error::ReadSheetDataError,
+ v1::constants::{
CURRENT_SHEET_VERSION, HEADER_SIZE, INDEX_ENTRY_SIZE, MAPPING_BUCKET_MIN_SIZE,
MAPPING_DIR_ENTRY_SIZE,
},
- error::ReadSheetDataError,
+ v1::writer::calculate_path_hash,
},
};
use std::collections::HashSet;
-/// Reconstruct complete SheetData from full sheet data
pub fn read_sheet_data(full_sheet_data: &[u8]) -> Result<SheetData, ReadSheetDataError> {
if full_sheet_data.len() < HEADER_SIZE {
return Err(std::io::Error::new(
@@ -125,7 +125,6 @@ pub fn read_sheet_data(full_sheet_data: &[u8]) -> Result<SheetData, ReadSheetDat
Ok(SheetData { mappings })
}
-/// Read mapping information for a specific node from complete sheet data
pub fn read_mapping<'a>(
full_sheet_data: &'a [u8],
node: &[&str],
@@ -176,7 +175,7 @@ pub fn read_mapping<'a>(
// Calculate hash prefix for target node
let node_path: Vec<String> = node.iter().map(|s| s.to_string()).collect();
- let target_hash = crate::sheet::writer::calculate_path_hash(&node_path);
+ let target_hash = calculate_path_hash(&node_path);
let target_bucket_key = target_hash >> 24; // Take high 8 bits as bucket key
// Find corresponding bucket in mapping directory using binary search
diff --git a/systems/sheet/src/sheet/v1/test.rs b/systems/sheet/src/sheet/v1/test.rs
index ae20be5..dfba3c8 100644
--- a/systems/sheet/src/sheet/v1/test.rs
+++ b/systems/sheet/src/sheet/v1/test.rs
@@ -4,7 +4,7 @@ use crate::{
index_source::IndexSource,
mapping::{LocalMapping, LocalMappingForward},
sheet::{
- SheetData, constants::HEADER_SIZE, reader::read_sheet_data,
+ SheetData, reader::read_sheet_data, v1::constants::HEADER_SIZE,
writer::convert_sheet_data_to_bytes,
},
};
diff --git a/systems/sheet/src/sheet/v1/writer.rs b/systems/sheet/src/sheet/v1/writer.rs
index 5d9b257..00f0987 100644
--- a/systems/sheet/src/sheet/v1/writer.rs
+++ b/systems/sheet/src/sheet/v1/writer.rs
@@ -1,13 +1,12 @@
use crate::index_source::IndexSource;
use crate::mapping::LocalMapping;
use crate::sheet::SheetData;
-use crate::sheet::constants::{
+use crate::sheet::v1::constants::{
CURRENT_SHEET_VERSION, HEADER_SIZE, INDEX_ENTRY_SIZE, MAPPING_DIR_ENTRY_SIZE,
};
use sha2::{Digest, Sha256};
use std::collections::{BTreeMap, HashMap};
-/// Convert SheetData to byte array
pub fn convert_sheet_data_to_bytes(sheet_data: SheetData) -> Vec<u8> {
// Collect all mappings
let mappings: Vec<LocalMapping> = sheet_data.mappings.into_iter().collect();
@@ -97,7 +96,6 @@ pub fn convert_sheet_data_to_bytes(sheet_data: SheetData) -> Vec<u8> {
result
}
-/// Calculate path hash (SHA256, take first 4 bytes)
pub fn calculate_path_hash(path: &[String]) -> u32 {
let mut hasher = Sha256::new();
for segment in path {
@@ -156,7 +154,7 @@ fn serialize_path(path: &[String]) -> Vec<u8> {
/// Test only: Calculate single mapping bucket entry size
#[cfg(test)]
fn calculate_mapping_bucket_size(mapping: &LocalMapping) -> usize {
- use crate::sheet::constants::MAPPING_BUCKET_MIN_SIZE;
+ use crate::sheet::v1::constants::MAPPING_BUCKET_MIN_SIZE;
let path_size = serialize_path(mapping.value()).len();
let (_, forward_info_len, _) = mapping.forward().unpack();
@@ -167,7 +165,7 @@ fn calculate_mapping_bucket_size(mapping: &LocalMapping) -> usize {
#[cfg(test)]
mod tests {
use super::*;
- use crate::{mapping::LocalMappingForward, sheet::constants::MAPPING_BUCKET_MIN_SIZE};
+ use crate::{mapping::LocalMappingForward, sheet::v1::constants::MAPPING_BUCKET_MIN_SIZE};
#[test]
fn test_serialize_path() {
diff --git a/systems/sheet/src/sheet/writer.rs b/systems/sheet/src/sheet/writer.rs
new file mode 100644
index 0000000..d9e31d7
--- /dev/null
+++ b/systems/sheet/src/sheet/writer.rs
@@ -0,0 +1,8 @@
+use crate::sheet::SheetData;
+
+include!("current.rs");
+
+/// Convert SheetData to byte array
+pub fn convert_sheet_data_to_bytes(sheet_data: SheetData) -> Vec<u8> {
+ writer::convert_sheet_data_to_bytes(sheet_data)
+}