bump dependencies #4
@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
- Bumped `thiserror` to v2
|
||||
- Bumped `spacepackets` to v0.13
|
||||
- The source and destination handlers can now be used without the `std` feature and only require
|
||||
the `alloc` feature.
|
||||
|
||||
# [v0.1.0] 2024-09-11
|
||||
|
||||
Initial release
|
||||
|
14
Cargo.toml
14
Cargo.toml
@ -18,18 +18,18 @@ name = "cfdp"
|
||||
[dependencies]
|
||||
crc = "3"
|
||||
smallvec = "1"
|
||||
derive-new = "0.6"
|
||||
derive-new = ">=0.6, <=0.7"
|
||||
|
||||
[dependencies.spacepackets]
|
||||
version = "0.12"
|
||||
version = "0.13"
|
||||
default-features = false
|
||||
|
||||
[dependencies.thiserror]
|
||||
version = "1"
|
||||
optional = true
|
||||
version = "2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.hashbrown]
|
||||
version = "0.14"
|
||||
version = ">=0.14, <=0.15"
|
||||
optional = true
|
||||
|
||||
[dependencies.serde]
|
||||
@ -44,7 +44,7 @@ optional = true
|
||||
default = ["std"]
|
||||
std = [
|
||||
"alloc",
|
||||
"thiserror",
|
||||
"thiserror/std",
|
||||
"spacepackets/std"
|
||||
]
|
||||
alloc = [
|
||||
@ -58,7 +58,7 @@ defmt = ["dep:defmt", "spacepackets/defmt"]
|
||||
tempfile = "3"
|
||||
rand = "0.8"
|
||||
log = "0.4"
|
||||
fern = "0.6"
|
||||
fern = "0.7"
|
||||
chrono = "0.4"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
|
||||
|
13
README.md
13
README.md
@ -14,14 +14,13 @@ The underlying base packet library used to generate the packets to be sent is th
|
||||
# Features
|
||||
|
||||
The goal of this library is to be flexible enough to support the use-cases of both on-board
|
||||
software and of ground software. It has support to make integration on [std] systems as simple
|
||||
as possible, but also has sufficient abstraction to allow for integration on`no_std` environments.
|
||||
Currently, the handlers still require the [std] feature until
|
||||
[thiserror supports `error_in_core`](https://github.com/dtolnay/thiserror/pull/304).
|
||||
software and of ground software. It has support to make integration on `std` systems as simple
|
||||
as possible, but also has sufficient abstraction to allow for integration on`no_std` environments
|
||||
and can be used on these systems as well as long as the `alloc` feature is activated.
|
||||
|
||||
It is recommended to activate the `alloc` feature at the very least to allow using the primary
|
||||
components provided by this crate. These components will only allocate memory at initialization
|
||||
time and thus are still viable for systems where run-time allocation is prohibited.
|
||||
Please note even though the `alloc` feature is required for the core handlers, these components
|
||||
will only allocate memory at initialization time and thus are still viable for systems where
|
||||
run-time allocation is prohibited.
|
||||
|
||||
## Default features
|
||||
|
||||
|
@ -55,7 +55,6 @@ use spacepackets::{
|
||||
},
|
||||
util::{UnsignedByteField, UnsignedEnum},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FileProperties {
|
||||
@ -189,7 +188,7 @@ impl<CheckTimer: CountdownProvider> TransactionParams<CheckTimer> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DestError {
|
||||
/// File directive expected, but none specified
|
||||
#[error("expected file directive")]
|
||||
@ -215,6 +214,7 @@ pub enum DestError {
|
||||
#[error("pdu error {0}")]
|
||||
Pdu(#[from] PduError),
|
||||
#[error("io error {0}")]
|
||||
#[cfg(feature = "std")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("file store error {0}")]
|
||||
Filestore(#[from] FilestoreError),
|
||||
|
124
src/filestore.rs
124
src/filestore.rs
@ -1,103 +1,38 @@
|
||||
use alloc::string::{String, ToString};
|
||||
use core::fmt::Display;
|
||||
use spacepackets::cfdp::ChecksumType;
|
||||
use spacepackets::ByteConversionError;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "std")]
|
||||
pub use std_mod::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum FilestoreError {
|
||||
#[error("file does not exist")]
|
||||
FileDoesNotExist,
|
||||
#[error("file already exists")]
|
||||
FileAlreadyExists,
|
||||
#[error("directory does not exist")]
|
||||
DirDoesNotExist,
|
||||
#[error("permission error")]
|
||||
Permission,
|
||||
#[error("is not a file")]
|
||||
IsNotFile,
|
||||
#[error("is not a directory")]
|
||||
IsNotDirectory,
|
||||
ByteConversion(ByteConversionError),
|
||||
Io {
|
||||
raw_errno: Option<i32>,
|
||||
string: String,
|
||||
},
|
||||
#[error("byte conversion: {0}")]
|
||||
ByteConversion(#[from] ByteConversionError),
|
||||
#[error("IO error: {0})")]
|
||||
#[cfg(feature = "std")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("checksum type not implemented: {0:?}")]
|
||||
ChecksumTypeNotImplemented(ChecksumType),
|
||||
#[error("utf8 error")]
|
||||
Utf8Error,
|
||||
#[error("other error")]
|
||||
Other,
|
||||
}
|
||||
|
||||
impl From<ByteConversionError> for FilestoreError {
|
||||
fn from(value: ByteConversionError) -> Self {
|
||||
Self::ByteConversion(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FilestoreError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
FilestoreError::FileDoesNotExist => {
|
||||
write!(f, "file does not exist")
|
||||
}
|
||||
FilestoreError::FileAlreadyExists => {
|
||||
write!(f, "file already exists")
|
||||
}
|
||||
FilestoreError::DirDoesNotExist => {
|
||||
write!(f, "directory does not exist")
|
||||
}
|
||||
FilestoreError::Permission => {
|
||||
write!(f, "permission error")
|
||||
}
|
||||
FilestoreError::IsNotFile => {
|
||||
write!(f, "is not a file")
|
||||
}
|
||||
FilestoreError::IsNotDirectory => {
|
||||
write!(f, "is not a directory")
|
||||
}
|
||||
FilestoreError::ByteConversion(e) => {
|
||||
write!(f, "filestore error: {e}")
|
||||
}
|
||||
FilestoreError::Io { raw_errno, string } => {
|
||||
write!(
|
||||
f,
|
||||
"filestore generic IO error with raw errno {:?}: {}",
|
||||
raw_errno, string
|
||||
)
|
||||
}
|
||||
FilestoreError::ChecksumTypeNotImplemented(checksum_type) => {
|
||||
write!(f, "checksum {:?} not implemented", checksum_type)
|
||||
}
|
||||
FilestoreError::Utf8Error => {
|
||||
write!(f, "utf8 error")
|
||||
}
|
||||
FilestoreError::Other => {
|
||||
write!(f, "some filestore error occured")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for FilestoreError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
FilestoreError::ByteConversion(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<std::io::Error> for FilestoreError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Self::Io {
|
||||
raw_errno: value.raw_os_error(),
|
||||
string: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VirtualFilestore {
|
||||
fn create_file(&self, file_path: &str) -> Result<(), FilestoreError>;
|
||||
|
||||
@ -122,14 +57,7 @@ pub trait VirtualFilestore {
|
||||
|
||||
fn filename_from_full_path(path: &str) -> Option<&str>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
// Convert the path string to a Path
|
||||
let path = Path::new(path);
|
||||
|
||||
// Extract the file name using the file_name() method
|
||||
path.file_name().and_then(|name| name.to_str())
|
||||
}
|
||||
Self: Sized;
|
||||
|
||||
fn is_file(&self, path: &str) -> Result<bool, FilestoreError>;
|
||||
|
||||
@ -193,7 +121,7 @@ pub mod std_mod {
|
||||
use super::*;
|
||||
use std::{
|
||||
fs::{self, File, OpenOptions},
|
||||
io::{BufReader, Read, Seek, SeekFrom, Write},
|
||||
io::{BufReader, Read, Seek, SeekFrom, Write}, path::Path,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
@ -241,10 +169,7 @@ pub mod std_mod {
|
||||
}
|
||||
|
||||
fn create_dir(&self, dir_path: &str) -> Result<(), FilestoreError> {
|
||||
fs::create_dir(dir_path).map_err(|e| FilestoreError::Io {
|
||||
raw_errno: e.raw_os_error(),
|
||||
string: e.to_string(),
|
||||
})?;
|
||||
fs::create_dir(dir_path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -358,6 +283,17 @@ pub mod std_mod {
|
||||
_ => Err(FilestoreError::ChecksumTypeNotImplemented(checksum_type)),
|
||||
}
|
||||
}
|
||||
|
||||
fn filename_from_full_path(path: &str) -> Option<&str>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
// Convert the path string to a Path
|
||||
let path = Path::new(path);
|
||||
|
||||
// Extract the file name using the file_name() method
|
||||
path.file_name().and_then(|name| name.to_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeFilestore {
|
||||
@ -393,7 +329,7 @@ pub mod std_mod {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs, path::Path, println};
|
||||
use std::{fs, path::Path, println, string::ToString};
|
||||
|
||||
use super::*;
|
||||
use alloc::format;
|
||||
|
28
src/lib.rs
28
src/lib.rs
@ -14,11 +14,12 @@
|
||||
//! The goal of this library is to be flexible enough to support the use-cases of both on-board
|
||||
//! software and of ground software. It has support to make integration on [std] systems as simple
|
||||
//! as possible, but also has sufficient abstraction to allow for integration on `no_std`
|
||||
//! environments. Currently, the handlers still require the [std] feature until
|
||||
//! [thiserror supports `error_in_core`](https://github.com/dtolnay/thiserror/pull/304).
|
||||
//! It is recommended to activate the `alloc` feature at the very least to allow using the primary
|
||||
//! components provided by this crate. These components will only allocate memory at initialization
|
||||
//! time and thus are still viable for systems where run-time allocation is prohibited.
|
||||
//! environments and can be used on these systems as well as long as the [alloc] feature is used
|
||||
//! as well.
|
||||
//!
|
||||
//! Please note even though the [alloc] feature is required for the core handlers, these components
|
||||
//! will only allocate memory at initialization time and thus are still viable for systems where
|
||||
//! run-time allocation is prohibited.
|
||||
//!
|
||||
//! The core of this library are the [crate::dest::DestinationHandler] and the
|
||||
//! [crate::source::SourceHandler] components which model the CFDP destination and source entity
|
||||
@ -70,12 +71,11 @@ extern crate alloc;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod dest;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod dest;
|
||||
pub mod filestore;
|
||||
pub mod request;
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod source;
|
||||
pub mod time;
|
||||
pub mod user;
|
||||
@ -83,8 +83,6 @@ pub mod user;
|
||||
use crate::time::CountdownProvider;
|
||||
use core::{cell::RefCell, fmt::Debug, hash::Hash};
|
||||
use crc::{Crc, CRC_32_ISCSI, CRC_32_ISO_HDLC};
|
||||
#[cfg(feature = "std")]
|
||||
use hashbrown::HashMap;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use alloc_mod::*;
|
||||
@ -288,12 +286,12 @@ pub trait RemoteEntityConfigProvider {
|
||||
fn remove_config(&mut self, remote_id: u64) -> bool;
|
||||
}
|
||||
|
||||
/// This is a thin wrapper around a [HashMap] to store remote entity configurations.
|
||||
/// This is a thin wrapper around a [hashbrown::HashMap] to store remote entity configurations.
|
||||
/// It implements the full [RemoteEntityConfigProvider] trait.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Default, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct StdRemoteEntityConfigProvider(pub HashMap<u64, RemoteEntityConfig>);
|
||||
pub struct StdRemoteEntityConfigProvider(pub hashbrown::HashMap<u64, RemoteEntityConfig>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl RemoteEntityConfigProvider for StdRemoteEntityConfigProvider {
|
||||
@ -879,7 +877,7 @@ impl<'raw> PduRawWithInfo<'raw> {
|
||||
});
|
||||
}
|
||||
if pdu_header.pdu_datafield_len() < 1 {
|
||||
return Err(PduError::FormatError);
|
||||
return Err(PduError::Format);
|
||||
}
|
||||
// Route depending on PDU type and directive type if applicable. Retrieve directive type
|
||||
// from the raw stream for better performance (with sanity and directive code check).
|
||||
@ -1548,7 +1546,7 @@ pub(crate) mod tests {
|
||||
|
||||
#[test]
|
||||
fn transaction_id_hashable_usable_as_map_key() {
|
||||
let mut map = HashMap::new();
|
||||
let mut map = hashbrown::HashMap::new();
|
||||
let transaction_id_0 = TransactionId::new(
|
||||
UnsignedByteFieldU8::new(1).into(),
|
||||
UnsignedByteFieldU8::new(2).into(),
|
||||
|
@ -748,25 +748,6 @@ impl<
|
||||
}
|
||||
|
||||
fn notice_of_completion(&mut self, cfdp_user: &mut impl CfdpUser) {
|
||||
/*
|
||||
def _notice_of_completion(self):
|
||||
if self.cfg.indication_cfg.transaction_finished_indication_required:
|
||||
assert self._params.transaction_id is not None
|
||||
# This happens for unacknowledged file copy operation with no closure.
|
||||
if self._params.finished_params is None:
|
||||
self._params.finished_params = FinishedParams(
|
||||
condition_code=ConditionCode.NO_ERROR,
|
||||
delivery_code=DeliveryCode.DATA_COMPLETE,
|
||||
file_status=FileStatus.FILE_STATUS_UNREPORTED,
|
||||
)
|
||||
indication_params = TransactionFinishedParams(
|
||||
transaction_id=self._params.transaction_id,
|
||||
finished_params=self._params.finished_params,
|
||||
)
|
||||
self.user.transaction_finished_indication(indication_params)
|
||||
# Transaction finished
|
||||
self.reset()
|
||||
*/
|
||||
let tstate = self.tstate.as_ref().unwrap();
|
||||
if self.local_cfg.indication_cfg.transaction_finished {
|
||||
// The first case happens for unacknowledged file copy operation with no closure.
|
||||
|
Loading…
Reference in New Issue
Block a user