1#![forbid(future_incompatible)]
2#![doc = include_str!("../README.md")]
4
5pub mod ids;
6pub mod l2cap;
7pub mod types;
8
9use types::{ActionRc, ListRc, OpType};
10
11pub type Result<T> = core::result::Result<T, Error>;
13
14#[derive(thiserror::Error, Debug)]
16pub enum Error {
17 #[error("Invalid UTF8 string: {0}")]
19 BadUtf8(#[from] core::str::Utf8Error),
20 #[error("Invalid UUID: {0}")]
22 BadUuid(#[from] uuid::Error),
23 #[error("Not supported")]
25 NotSupported,
26 #[error("Not found")]
28 NotFound,
29 #[error("No response")]
31 NoResponse,
32 #[error("Invalid response")]
34 BadResponse,
35 #[error("Invalid UUID size: {0}")]
37 BadUuidSize(usize),
38 #[error("Object list error: {0:?}")]
40 ListError(#[from] ListRc),
41 #[error("Object action error: {0:?}")]
43 ActionError(#[from] ActionRc),
44 #[error("Invalid action features: {0:08x?}")]
46 BadActionFeatures(u32),
47 #[error("Invalid list features: {0:08x?}")]
49 BadListFeatures(u32),
50 #[error("Invalid properties: {0:08x?}")]
52 BadProperties(u32),
53 #[error("Invalid directory flags: {0:02x?}")]
55 BadDirFlags(u8),
56 #[error("Not enough data ({actual} < {needed})")]
58 NotEnoughData {
59 actual: usize,
61 needed: usize,
63 },
64 #[error("Too many data ({actual} > {needed})")]
66 TooManyData {
67 actual: usize,
69 needed: usize,
71 },
72 #[error("Invalid opcode for {type_}: {code:02x?}")]
74 BadOpCode {
75 type_: OpType,
77 code: u8,
79 },
80}
81
82impl From<std::string::FromUtf8Error> for Error {
83 fn from(err: std::string::FromUtf8Error) -> Self {
84 Self::BadUtf8(err.utf8_error())
85 }
86}
87
88impl Error {
89 pub fn check_len(actual: usize, needed: usize) -> Result<()> {
91 if actual < needed {
92 Err(Error::NotEnoughData { actual, needed })
93 } else {
94 Ok(())
95 }
96 }
97
98 pub fn check_size<T: Sized>(actual: usize) -> Result<()> {
100 Self::check_len(actual, core::mem::size_of::<T>())
101 }
102
103 pub fn check_len_exact(actual: usize, needed: usize) -> Result<()> {
105 Self::check_len(actual, needed)?;
106 if actual > needed {
107 Err(Error::TooManyData { actual, needed })
108 } else {
109 Ok(())
110 }
111 }
112
113 pub fn check_size_exact<T: Sized>(actual: usize) -> Result<()> {
115 Self::check_len_exact(actual, core::mem::size_of::<T>())
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
121#[repr(C)]
122pub struct Sizes {
123 pub current: usize,
125 pub allocated: usize,
127}
128
129impl From<&[u8; 8]> for Sizes {
130 fn from(raw: &[u8; 8]) -> Self {
131 let sizes = types::Sizes::from(raw);
132 Self {
133 current: sizes.current as _,
134 allocated: sizes.allocated as _,
135 }
136 }
137}
138
139impl TryFrom<&[u8]> for Sizes {
140 type Error = Error;
141
142 fn try_from(raw: &[u8]) -> Result<Self> {
143 Error::check_size_exact::<types::Sizes>(raw.len())?;
144 let sizes = types::Sizes::try_from(raw)?;
145 Ok(Self {
146 current: sizes.current as _,
147 allocated: sizes.allocated as _,
148 })
149 }
150}