Implement optional JPEG2000 codec adapter (#40)
Some checks failed
JPEG 2000 feature / linux (push) Has been cancelled
JPEG 2000 feature / macos (push) Has been cancelled
JPEG 2000 feature / windows (push) Has been cancelled

This commit is contained in:
2026-08-09 03:42:18 +00:00
parent 5d1573fc82
commit 16501f2331
24 changed files with 2776 additions and 53 deletions

View File

@@ -4,7 +4,9 @@
//! surfaces. Their behavior is implemented only when the owning API slice is
//! ported.
use std::any::Any;
use std::collections::BTreeMap;
use std::fmt;
use std::future::Future;
use std::hash::Hash;
use std::marker::PhantomData;
@@ -20,6 +22,54 @@ pub trait ReadWrite: std::io::Read + std::io::Write + std::io::Seek {}
impl<T: std::io::Read + std::io::Write + std::io::Seek> ReadWrite for T {}
trait OpaqueValue: Any + fmt::Debug + Send + Sync {
fn as_any(&self) -> &dyn Any;
fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
}
impl<T: Any + fmt::Debug + Send + Sync> OpaqueValue for T {
fn as_any(&self) -> &dyn Any {
self
}
fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
self
}
}
/// A type-erased reference value used when a mapped `System.Object` carries a
/// project type rather than one of the protocol scalar variants.
///
/// Equality and hashing use reference identity, matching the default behavior
/// of arbitrary CLR reference objects. The contained value can be recovered
/// with [`Object::downcast_ref`].
#[derive(Clone)]
pub struct OpaqueObject(Arc<dyn OpaqueValue>);
impl fmt::Debug for OpaqueObject {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_tuple("OpaqueObject")
.field(&self.0)
.finish()
}
}
impl PartialEq for OpaqueObject {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.0, &other.0)
}
}
impl Eq for OpaqueObject {}
impl Hash for OpaqueObject {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let pointer = Arc::as_ptr(&self.0).cast::<()>();
pointer.hash(state);
}
}
#[derive(Clone, Debug)]
pub enum Object {
Undefined,
@@ -43,6 +93,34 @@ pub enum Object {
Vector3(crate::Vector3),
Vector3d(crate::Vector3d),
Vector4(crate::Vector4),
/// A project-owned value passed through a mapped `System.Object` boundary.
Opaque(OpaqueObject),
}
impl Object {
/// Boxes a project-owned value for a mapped `System.Object` parameter.
#[must_use]
pub fn opaque<T: Any + fmt::Debug + Send + Sync>(value: T) -> Self {
Self::Opaque(OpaqueObject(Arc::new(value)))
}
/// Borrows an opaque value when its concrete type is `T`.
#[must_use]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
match self {
Self::Opaque(value) => value.0.as_ref().as_any().downcast_ref(),
_ => None,
}
}
/// Clones the opaque reference and recovers its concrete shared value.
#[must_use]
pub fn downcast_arc<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
match self {
Self::Opaque(value) => value.0.clone().into_any().downcast().ok(),
_ => None,
}
}
}
impl PartialEq for Object {
@@ -69,6 +147,7 @@ impl PartialEq for Object {
(Self::Vector3(lhs), Self::Vector3(rhs)) => crate::Vector3::eq(*lhs, *rhs),
(Self::Vector3d(lhs), Self::Vector3d(rhs)) => crate::Vector3d::eq(*lhs, *rhs),
(Self::Vector4(lhs), Self::Vector4(rhs)) => crate::Vector4::eq(*lhs, *rhs),
(Self::Opaque(lhs), Self::Opaque(rhs)) => lhs == rhs,
_ => false,
}
}
@@ -105,6 +184,7 @@ impl std::hash::Hash for Object {
Self::Vector3(value) => value.get_hash_code().hash(state),
Self::Vector3d(value) => value.get_hash_code().hash(state),
Self::Vector4(value) => value.get_hash_code().hash(state),
Self::Opaque(value) => value.hash(state),
}
}
}
@@ -379,9 +459,10 @@ pub struct SocketException;
#[cfg(test)]
mod tests {
use super::{CancellationToken, HttpMessageHandler, HttpRequest, HttpResponse, Uri};
use super::{CancellationToken, HttpMessageHandler, HttpRequest, HttpResponse, Object, Uri};
use std::collections::BTreeMap;
use std::future::Future;
use std::sync::Arc;
use std::task::{Context, Poll, Waker};
#[test]
@@ -427,4 +508,22 @@ mod tests {
.is_success_status_code()
);
}
#[test]
fn opaque_objects_downcast_and_preserve_reference_identity() {
let object = Object::opaque(String::from("managed image boundary"));
assert_eq!(
object.downcast_ref::<String>().map(String::as_str),
Some("managed image boundary")
);
assert!(object.downcast_ref::<Vec<u8>>().is_none());
let first = object.downcast_arc::<String>().expect("shared string");
let second = object.downcast_arc::<String>().expect("shared string");
assert!(Arc::ptr_eq(&first, &second));
assert_eq!(object, object.clone());
assert_ne!(
object,
Object::opaque(String::from("managed image boundary"))
);
}
}