1use std::{
3 borrow::Cow,
4 fmt::{Debug, Display, Formatter},
5};
6
7pub mod mtd;
8
9pub mod v1v2;
10pub mod v3;
11
12fn chrp_checksum_add(lhs: u8, rhs: u8) -> u8 {
13 let (out, carry) = lhs.overflowing_add(rhs);
14 if carry {
15 out + 1
16 } else {
17 out
18 }
19}
20
21fn slice_rstrip<'a, T: PartialEq<T>>(mut ts: &'a [T], t: &T) -> &'a [T] {
22 while let Some(last) = ts.last() {
23 if last == t {
24 ts = ts.split_last().unwrap().1;
25 } else {
26 break;
27 }
28 }
29 ts
30}
31
32fn slice_find<T: PartialEq<T>>(ts: &[T], t: &T) -> Option<usize> {
33 let mut ret = None;
34 for (i, v) in ts.iter().enumerate() {
35 if v == t {
36 ret = Some(i);
37 break;
38 }
39 }
40 ret
41}
42
43#[derive(Debug)]
44pub enum Error {
45 ParseError,
46 SectionTooBig,
47 ApplyError(std::io::Error),
48}
49
50type Result<T> = std::result::Result<T, Error>;
51
52#[derive(Clone, Copy, PartialEq)]
53pub enum VarType {
54 Common,
55 System,
56}
57
58impl Display for VarType {
59 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
60 match self {
61 &VarType::Common => write!(f, "common"),
62 &VarType::System => write!(f, "system"),
63 }
64 }
65}
66
67pub fn nvram_parse<'a>(nvr: &'a [u8]) -> Result<Box<dyn Nvram<'a> + 'a>> {
68 match (v3::Nvram::parse(nvr), v1v2::Nvram::parse(nvr)) {
69 (Ok(nvram_v3), Err(_)) => Ok(Box::new(nvram_v3)),
70 (Err(_), Ok(nvram_v1v2)) => Ok(Box::new(nvram_v1v2)),
71 _ => Err(Error::ParseError),
72 }
73}
74
75pub trait NvramWriter {
76 fn erase_if_needed(&mut self, offset: u32, size: usize);
77 fn write_all(&mut self, offset: u32, buf: &[u8]) -> std::io::Result<()>;
78}
79
80pub trait Nvram<'a> {
81 fn prepare_for_write(&mut self);
82 fn active_part_mut(&mut self) -> &mut dyn Partition<'a>;
83 fn partitions(&self) -> Box<dyn Iterator<Item = &dyn Partition<'a>> + '_>;
84 fn serialize(&self) -> Result<Vec<u8>>;
85 fn apply(&mut self, w: &mut dyn NvramWriter) -> Result<()>;
86}
87
88pub trait Partition<'a>: Display {
89 fn variables(&self) -> Box<dyn Iterator<Item = &dyn Variable<'a>> + '_>;
90 fn get_variable(&self, key: &[u8], typ: VarType) -> Option<&dyn Variable<'a>>;
91 fn insert_variable(&mut self, key: &[u8], value: Cow<'a, [u8]>, typ: VarType);
92 fn remove_variable(&mut self, key: &[u8], typ: VarType);
93}
94
95pub trait Variable<'a>: Display {
96 fn value(&self) -> Cow<'a, [u8]>;
97}