Skip to content

Commit

Permalink
Add the identity codec
Browse files Browse the repository at this point in the history
  • Loading branch information
juntyr committed Aug 6, 2024
1 parent 10950a5 commit 14a3278
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"crates/numcodecs-python",

"codecs/bit-round",
"codecs/identity",
]

[workspace.package]
Expand All @@ -21,6 +22,7 @@ numcodecs-python = { version = "0.1", path = "crates/numcodecs-python", default-

# workspace-internal codecs crates
numcodecs-bit-round = { version = "0.1", path = "codecs/bit-round", default-features = false }
numcodecs-identity = { version = "0.1", path = "codecs/identity", default-features = false }

# crates.io third-party dependencies
convert_case = { version = "0.6", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions codecs/bit-round/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ impl Codec for BitRoundCodec {

fn decode(&self, encoded: AnyCowArray) -> Result<AnyArray, Self::Error> {
match encoded {
AnyCowArray::F32(encoded) => Ok(AnyArray::F32(encoded.to_owned())),
AnyCowArray::F64(encoded) => Ok(AnyArray::F64(encoded.to_owned())),
AnyCowArray::F32(encoded) => Ok(AnyArray::F32(encoded.into_owned())),
AnyCowArray::F64(encoded) => Ok(AnyArray::F64(encoded.into_owned())),
encoded => Err(BitRoundError::UnsupportedDtype(encoded.dtype())),
}
}
Expand Down
23 changes: 23 additions & 0 deletions codecs/identity/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "numcodecs-identity"
version = "0.1.0"
edition = { workspace = true }
authors = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }

description = "Identity codec implementation for the numcodecs API"
readme = "README.md"
categories = ["compression", "encoding"]
keywords = ["identity", "numcodecs", "compression", "encoding"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
numcodecs = { workspace = true }
serde = { workspace = true, features = ["std", "derive"] }
thiserror = { workspace = true }

[lints]
workspace = true
1 change: 1 addition & 0 deletions codecs/identity/LICENSE
32 changes: 32 additions & 0 deletions codecs/identity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[![CI Status]][workflow] [![MSRV]][repo] [![Latest Version]][crates.io] [![Rust Doc Crate]][docs.rs] [![Rust Doc Main]][docs]

[CI Status]: https://img.shields.io/github/actions/workflow/status/juntyr/numcodecs-rs/ci.yml?branch=main
[workflow]: https://github.com/juntyr/numcodecs-rs/actions/workflows/ci.yml?query=branch%3Amain

[MSRV]: https://img.shields.io/badge/MSRV-1.64.0-blue
[repo]: https://github.com/juntyr/numcodecs-rs

[Latest Version]: https://img.shields.io/crates/v/numcodecs-identity
[crates.io]: https://crates.io/crates/numcodecs-identity

[Rust Doc Crate]: https://img.shields.io/docsrs/numcodecs-identity
[docs.rs]: https://docs.rs/numcodecs-identity/

[Rust Doc Main]: https://img.shields.io/badge/docs-main-blue
[docs]: https://juntyr.github.io/numcodecs-rs/numcodecs-identity

# numcodecs-identity

Identity codec implementation for the [`numcodecs`] API.

[`numcodecs`]: https://docs.rs/numcodecs/0.1/numcodecs/

## License

Licensed under the Mozilla Public License, Version 2.0 ([LICENSE](LICENSE) or https://www.mozilla.org/en-US/MPL/2.0/).

## Funding

The `numcodecs-identity` crate has been developed as part of [ESiWACE3](https://www.esiwace.eu), the third phase of the Centre of Excellence in Simulation of Weather and Climate in Europe.

Funded by the European Union. This work has received funding from the European High Performance Computing Joint Undertaking (JU) under grant agreement No 101093054.
111 changes: 111 additions & 0 deletions codecs/identity/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//! [![CI Status]][workflow] [![MSRV]][repo] [![Latest Version]][crates.io] [![Rust Doc Crate]][docs.rs] [![Rust Doc Main]][docs]
//!
//! [CI Status]: https://img.shields.io/github/actions/workflow/status/juntyr/numcodecs-rs/ci.yml?branch=main
//! [workflow]: https://github.com/juntyr/numcodecs-rs/actions/workflows/ci.yml?query=branch%3Amain
//!
//! [MSRV]: https://img.shields.io/badge/MSRV-1.64.0-blue
//! [repo]: https://github.com/juntyr/numcodecs-rs
//!
//! [Latest Version]: https://img.shields.io/crates/v/numcodecs-identity
//! [crates.io]: https://crates.io/crates/numcodecs-identity
//!
//! [Rust Doc Crate]: https://img.shields.io/docsrs/numcodecs-identity
//! [docs.rs]: https://docs.rs/numcodecs-identity/
//!
//! [Rust Doc Main]: https://img.shields.io/badge/docs-main-blue
//! [docs]: https://juntyr.github.io/numcodecs-rs/numcodecs-identity
//!
//! Bit rounding codec implementation for the [`numcodecs`] API.
use numcodecs::{
AnyArray, AnyArrayDType, AnyArrayView, AnyArrayViewMut, AnyCowArray, Codec, StaticCodec,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use thiserror::Error;

#[derive(Clone, Serialize, Deserialize)]
/// Identity codec which applies the identity function, i.e. passes through the
/// input unchanged during encoding and decoding.
pub struct IdentityCodec;

impl Codec for IdentityCodec {
type Error = IdentityCodecError;

fn encode(&self, data: AnyCowArray) -> Result<AnyArray, Self::Error> {
Ok(data.into_owned())
}

fn decode(&self, encoded: AnyCowArray) -> Result<AnyArray, Self::Error> {
Ok(encoded.into_owned())
}

fn decode_into(
&self,
encoded: AnyArrayView,
mut decoded: AnyArrayViewMut,
) -> Result<(), Self::Error> {
#[allow(clippy::unit_arg)]
match (&encoded, &mut decoded) {
(AnyArrayView::U8(encoded), AnyArrayViewMut::U8(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::U16(encoded), AnyArrayViewMut::U16(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::U32(encoded), AnyArrayViewMut::U32(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::U64(encoded), AnyArrayViewMut::U64(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::I8(encoded), AnyArrayViewMut::I8(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::I16(encoded), AnyArrayViewMut::I16(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::I32(encoded), AnyArrayViewMut::I32(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::I64(encoded), AnyArrayViewMut::I64(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::F32(encoded), AnyArrayViewMut::F32(decoded)) => {
Ok(decoded.assign(encoded))
}
(AnyArrayView::F64(encoded), AnyArrayViewMut::F64(decoded)) => {
Ok(decoded.assign(encoded))
}
(encoded, decoded) => Err(IdentityCodecError::MismatchedDecodeIntoDtype {
decoded: encoded.dtype(),
provided: decoded.dtype(),
}),
}
}

fn get_config<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.serialize(serializer)
}
}

impl StaticCodec for IdentityCodec {
const CODEC_ID: &'static str = "identity";

fn from_config<'de, D: Deserializer<'de>>(config: D) -> Result<Self, D::Error> {
Self::deserialize(config)
}
}

#[derive(Debug, Error)]
/// Errors that may occur when applying the [`IdentityCodec`].
pub enum IdentityCodecError {
/// [`IdentityCodec`] cannot decode the `decoded` dtype into the `provided`
/// array
#[error("Identity cannot decode the dtype {decoded} into the provided {provided} array")]
MismatchedDecodeIntoDtype {
/// Dtype of the `decoded` data
decoded: AnyArrayDType,
/// Dtype of the `provided` array into which the data is to be decoded
provided: AnyArrayDType,
},
}
18 changes: 18 additions & 0 deletions crates/numcodecs/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,24 @@ where
Self::F64(a) => AnyCowArray::F64(a.into()),
}
}

#[must_use]
/// Turns the array into a uniquely owned array, cloning the array elements
/// if necessary.
pub fn into_owned(self) -> AnyArray {
match self {
Self::U8(a) => AnyArray::U8(a.into_owned()),
Self::U16(a) => AnyArray::U16(a.into_owned()),
Self::U32(a) => AnyArray::U32(a.into_owned()),
Self::U64(a) => AnyArray::U64(a.into_owned()),
Self::I8(a) => AnyArray::I8(a.into_owned()),
Self::I16(a) => AnyArray::I16(a.into_owned()),
Self::I32(a) => AnyArray::I32(a.into_owned()),
Self::I64(a) => AnyArray::I64(a.into_owned()),
Self::F32(a) => AnyArray::F32(a.into_owned()),
Self::F64(a) => AnyArray::F64(a.into_owned()),
}
}
}

impl<T: AnyRawData> AnyArrayBase<T>
Expand Down

0 comments on commit 14a3278

Please sign in to comment.