Merge pull request #847 from mahkoh/jorth/various-refactors
Various refactors
This commit is contained in:
commit
b87eb60e68
19 changed files with 146 additions and 177 deletions
|
|
@ -10,13 +10,13 @@ use {
|
||||||
wl_display::WlDisplay,
|
wl_display::WlDisplay,
|
||||||
wl_registry::WlRegistry,
|
wl_registry::WlRegistry,
|
||||||
wl_surface::{WlSurface, commit_timeline::CommitTimelines},
|
wl_surface::{WlSurface, commit_timeline::CommitTimelines},
|
||||||
|
xdg_activation_token_v1::ActivationToken,
|
||||||
},
|
},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Interface, Object, ObjectId, WL_DISPLAY_ID},
|
object::{Interface, Object, ObjectId, WL_DISPLAY_ID},
|
||||||
security_context_acceptor::AcceptorMetadata,
|
security_context_acceptor::AcceptorMetadata,
|
||||||
state::State,
|
state::State,
|
||||||
utils::{
|
utils::{
|
||||||
activation_token::ActivationToken,
|
|
||||||
asyncevent::AsyncEvent,
|
asyncevent::AsyncEvent,
|
||||||
buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain},
|
buffd::{MsgFormatter, MsgParser, MsgParserError, OutBufferSwapchain},
|
||||||
copyhashmap::{CopyHashMap, Locked},
|
copyhashmap::{CopyHashMap, Locked},
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,12 @@ use {
|
||||||
config::handler::ConfigProxyHandler,
|
config::handler::ConfigProxyHandler,
|
||||||
ifs::wl_seat::SeatId,
|
ifs::wl_seat::SeatId,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{TileState, ToplevelData},
|
tree::{TileState, ToplevelData, ToplevelIdentifier},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
nice::{JAY_NO_REALTIME, dont_allow_config_so},
|
nice::{JAY_NO_REALTIME, dont_allow_config_so},
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
ptr_ext::PtrExt,
|
ptr_ext::PtrExt,
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
unlink_on_drop::UnlinkOnDrop,
|
unlink_on_drop::UnlinkOnDrop,
|
||||||
xrd::xrd,
|
xrd::xrd,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ use {
|
||||||
tagged_acceptor::TaggedAcceptorError,
|
tagged_acceptor::TaggedAcceptorError,
|
||||||
theme::{ThemeColor, ThemeSized},
|
theme::{ThemeColor, ThemeSized},
|
||||||
tree::{
|
tree::{
|
||||||
ContainerSplit, OutputNode, TearingMode, TileState, ToplevelData, ToplevelNode,
|
ContainerSplit, OutputNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier,
|
||||||
VrrMode, WorkspaceNode, toplevel_create_split, toplevel_parent_container,
|
ToplevelNode, VrrMode, WorkspaceNode, toplevel_create_split, toplevel_parent_container,
|
||||||
toplevel_set_floating, toplevel_set_workspace,
|
toplevel_set_floating, toplevel_set_workspace,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
|
|
@ -40,7 +40,6 @@ use {
|
||||||
oserror::{OsError, OsErrorExt},
|
oserror::{OsError, OsErrorExt},
|
||||||
stack::Stack,
|
stack::Stack,
|
||||||
timer::{TimerError, TimerFd},
|
timer::{TimerError, TimerFd},
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bincode::Options,
|
bincode::Options,
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,8 @@ use {
|
||||||
criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher},
|
criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher},
|
||||||
egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW,
|
egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW,
|
||||||
state::State,
|
state::State,
|
||||||
tree::ToplevelData,
|
tree::{ToplevelData, ToplevelIdentifier},
|
||||||
utils::{
|
utils::{copyhashmap::CopyHashMap, static_text::StaticText},
|
||||||
copyhashmap::CopyHashMap, static_text::StaticText,
|
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
egui::{
|
egui::{
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,11 @@ use {
|
||||||
criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher},
|
criteria::{CritMgrExt, CritUpstreamNode, crit_leaf::CritLeafMatcher},
|
||||||
egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW,
|
egui_adapter::egui_platform::icons::ICON_OPEN_IN_NEW,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{NodeId, ToplevelData, ToplevelNode, ToplevelType},
|
tree::{NodeId, ToplevelData, ToplevelIdentifier, ToplevelNode, ToplevelType},
|
||||||
utils::{
|
utils::{
|
||||||
copyhashmap::CopyHashMap,
|
copyhashmap::CopyHashMap,
|
||||||
event_listener::{EventListener, LazyEventSourceListener},
|
event_listener::{EventListener, LazyEventSourceListener},
|
||||||
static_text::StaticText,
|
static_text::StaticText,
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,8 @@ use {
|
||||||
},
|
},
|
||||||
ifs::wl_seat::WlSeatGlobal,
|
ifs::wl_seat::WlSeatGlobal,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{NodeId, ToplevelData, ToplevelNode},
|
tree::{NodeId, ToplevelData, ToplevelIdentifier, ToplevelNode},
|
||||||
utils::{
|
utils::{copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, queue::AsyncQueue},
|
||||||
copyhashmap::CopyHashMap, hash_map_ext::HashMapExt, queue::AsyncQueue,
|
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
jay_config::window::{ContentType, WindowType},
|
jay_config::window::{ContentType, WindowType},
|
||||||
linearize::static_map,
|
linearize::static_map,
|
||||||
|
|
|
||||||
|
|
@ -18,53 +18,6 @@ macro_rules! egl_transparent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! dynload {
|
|
||||||
(
|
|
||||||
$item:ident: $container:ident from $name:literal {
|
|
||||||
$(
|
|
||||||
$fun:ident: $ty:ty,
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
#[expect(non_snake_case)]
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct $container {
|
|
||||||
_lib: libloading::Library,
|
|
||||||
$(
|
|
||||||
pub $fun: $ty,
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static $item: std::sync::LazyLock<Option<$container>> = std::sync::LazyLock::new(|| unsafe {
|
|
||||||
use crate::utils::errorfmt::ErrorFmt;
|
|
||||||
let lib = match libloading::Library::new($name) {
|
|
||||||
Ok(l) => l,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Could not load lib{}: {}", $name, ErrorFmt(e));
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$(
|
|
||||||
#[expect(non_snake_case)]
|
|
||||||
let $fun: $ty =
|
|
||||||
match lib.get(stringify!($fun).as_bytes()) {
|
|
||||||
Ok(s) => *s,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Could not load {} from {}: {}", stringify!($fun), $name, ErrorFmt(e));
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
)*
|
|
||||||
Some($container {
|
|
||||||
_lib: lib,
|
|
||||||
$(
|
|
||||||
$fun,
|
|
||||||
)*
|
|
||||||
})
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
cmm::cmm_eotf::Eotf,
|
cmm::cmm_eotf::Eotf,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ use {
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
screenshoter::take_screenshot,
|
screenshoter::take_screenshot,
|
||||||
utils::{errorfmt::ErrorFmt, toplevel_identifier::ToplevelIdentifier},
|
tree::ToplevelIdentifier,
|
||||||
|
utils::errorfmt::ErrorFmt,
|
||||||
wire::{
|
wire::{
|
||||||
JayCompositorId, JayScreenshotId,
|
JayCompositorId, JayScreenshotId,
|
||||||
jay_compositor::{self, *},
|
jay_compositor::{self, *},
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@ use {
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
tree::{
|
tree::{
|
||||||
self, ContainerNode, DisplayNode, FloatNode, Node, NodeVisitor, OutputNode,
|
self, ContainerNode, DisplayNode, FloatNode, Node, NodeVisitor, OutputNode,
|
||||||
PlaceholderNode, ToplevelData, ToplevelNodeBase, ToplevelType, WorkspaceNode,
|
PlaceholderNode, ToplevelData, ToplevelIdentifier, ToplevelNodeBase, ToplevelType,
|
||||||
|
WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{opaque::OpaqueError, opt::Opt, toplevel_identifier::ToplevelIdentifier},
|
utils::{opaque::OpaqueError, opt::Opt},
|
||||||
wire::{JayTreeQueryId, jay_tree_query::*},
|
wire::{JayTreeQueryId, jay_tree_query::*},
|
||||||
},
|
},
|
||||||
isnt::std_1::primitive::IsntStrExt,
|
isnt::std_1::primitive::IsntStrExt,
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ use {
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
utils::activation_token::{ActivationToken, activation_token},
|
|
||||||
wire::{XdgActivationTokenV1Id, xdg_activation_token_v1::*},
|
wire::{XdgActivationTokenV1Id, xdg_activation_token_v1::*},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, rc::Rc},
|
std::{cell::Cell, rc::Rc},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
opaque!(ActivationToken, activation_token);
|
||||||
|
|
||||||
const MAX_TOKENS_PER_CLIENT: usize = 8;
|
const MAX_TOKENS_PER_CLIENT: usize = 8;
|
||||||
|
|
||||||
pub struct XdgActivationTokenV1 {
|
pub struct XdgActivationTokenV1 {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
globals::{Global, GlobalName},
|
globals::{Global, GlobalName},
|
||||||
ifs::xdg_activation_token_v1::XdgActivationTokenV1,
|
ifs::xdg_activation_token_v1::{ActivationToken, XdgActivationTokenV1},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
utils::{activation_token::ActivationToken, errorfmt::ErrorFmt, opaque::OpaqueError},
|
utils::{errorfmt::ErrorFmt, opaque::OpaqueError},
|
||||||
wire::{XdgActivationV1Id, xdg_activation_v1::*},
|
wire::{XdgActivationV1Id, xdg_activation_v1::*},
|
||||||
},
|
},
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
|
|
|
||||||
|
|
@ -853,3 +853,83 @@ macro_rules! dbg {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! dynload {
|
||||||
|
(
|
||||||
|
$item:ident: $container:ident from $name:literal {
|
||||||
|
$(
|
||||||
|
$fun:ident: $ty:ty,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
#[expect(non_snake_case)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct $container {
|
||||||
|
_lib: libloading::Library,
|
||||||
|
$(
|
||||||
|
pub $fun: $ty,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static $item: std::sync::LazyLock<Option<$container>> = std::sync::LazyLock::new(|| unsafe {
|
||||||
|
use crate::utils::errorfmt::ErrorFmt;
|
||||||
|
let lib = match libloading::Library::new($name) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not load {}: {}", $name, ErrorFmt(e));
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$(
|
||||||
|
#[allow(clippy::allow_attributes, non_snake_case)]
|
||||||
|
let $fun: $ty =
|
||||||
|
match lib.get(stringify!($fun).as_bytes()) {
|
||||||
|
Ok(s) => *s,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not load {} from {}: {}", stringify!($fun), $name, ErrorFmt(e));
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
)*
|
||||||
|
Some($container {
|
||||||
|
_lib: lib,
|
||||||
|
$(
|
||||||
|
$fun,
|
||||||
|
)*
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! opaque {
|
||||||
|
($ty:ident, $fun:ident) => {
|
||||||
|
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Ord, PartialOrd)]
|
||||||
|
pub struct $ty(crate::utils::opaque::Opaque);
|
||||||
|
|
||||||
|
unsafe impl crate::utils::clonecell::UnsafeCellCloneSafe for $ty {}
|
||||||
|
|
||||||
|
pub fn $fun() -> $ty {
|
||||||
|
$ty(crate::utils::opaque::opaque())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $ty {
|
||||||
|
pub fn to_string(self) -> arrayvec::ArrayString<{ crate::utils::opaque::OPAQUE_LEN }> {
|
||||||
|
self.0.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for $ty {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for $ty {
|
||||||
|
type Err = crate::utils::opaque::OpaqueError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(Self(s.parse()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ use {
|
||||||
workspace_manager::WorkspaceManagerState,
|
workspace_manager::WorkspaceManagerState,
|
||||||
wp_drm_lease_connector_v1::WpDrmLeaseConnectorV1,
|
wp_drm_lease_connector_v1::WpDrmLeaseConnectorV1,
|
||||||
wp_drm_lease_device_v1::WpDrmLeaseDeviceV1Global,
|
wp_drm_lease_device_v1::WpDrmLeaseDeviceV1Global,
|
||||||
|
xdg_activation_token_v1::ActivationToken,
|
||||||
zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1,
|
zwlr_foreign_toplevel_manager_v1::ZwlrForeignToplevelManagerV1,
|
||||||
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
|
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
|
||||||
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
|
zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1,
|
||||||
|
|
@ -107,13 +108,12 @@ use {
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode,
|
ContainerNode, ContainerSplit, Direction, DisplayNode, FindTreeUsecase, FloatNode,
|
||||||
FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode,
|
FoundNode, LatchListener, Node, NodeIds, NodeVisitorBase, OutputNode, PlaceholderNode,
|
||||||
TearingMode, TileState, ToplevelData, ToplevelNode, ToplevelNodeBase, Transform,
|
TearingMode, TileState, ToplevelData, ToplevelIdentifier, ToplevelNode,
|
||||||
VrrMode, WorkspaceDisplayOrder, WorkspaceNode, WsMoveConfig, generic_node_visitor,
|
ToplevelNodeBase, Transform, VrrMode, WorkspaceDisplayOrder, WorkspaceNode,
|
||||||
move_ws_to_output,
|
WsMoveConfig, generic_node_visitor, move_ws_to_output,
|
||||||
},
|
},
|
||||||
udmabuf::UdmabufHolder,
|
udmabuf::UdmabufHolder,
|
||||||
utils::{
|
utils::{
|
||||||
activation_token::ActivationToken,
|
|
||||||
asyncevent::AsyncEvent,
|
asyncevent::AsyncEvent,
|
||||||
bindings::Bindings,
|
bindings::Bindings,
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
|
|
@ -128,7 +128,6 @@ use {
|
||||||
queue::AsyncQueue,
|
queue::AsyncQueue,
|
||||||
refcounted::RefCounted,
|
refcounted::RefCounted,
|
||||||
run_toplevel::RunToplevel,
|
run_toplevel::RunToplevel,
|
||||||
toplevel_identifier::ToplevelIdentifier,
|
|
||||||
},
|
},
|
||||||
video::{
|
video::{
|
||||||
dmabuf::DmaBufIds,
|
dmabuf::DmaBufIds,
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,9 @@ use {
|
||||||
NodeLayerLink, OutputNode, PlaceholderNode, WorkspaceNode,
|
NodeLayerLink, OutputNode, PlaceholderNode, WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
array_to_tuple::ArrayToTuple,
|
array_to_tuple::ArrayToTuple, clonecell::CloneCell, copyhashmap::CopyHashMap,
|
||||||
clonecell::CloneCell,
|
event_listener::LazyEventSource, hash_map_ext::HashMapExt, numcell::NumCell,
|
||||||
copyhashmap::CopyHashMap,
|
rc_eq::rc_eq, threshold_counter::ThresholdCounter,
|
||||||
event_listener::LazyEventSource,
|
|
||||||
hash_map_ext::HashMapExt,
|
|
||||||
numcell::NumCell,
|
|
||||||
rc_eq::rc_eq,
|
|
||||||
threshold_counter::ThresholdCounter,
|
|
||||||
toplevel_identifier::{ToplevelIdentifier, toplevel_identifier},
|
|
||||||
},
|
},
|
||||||
wire::{
|
wire::{
|
||||||
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId,
|
ExtForeignToplevelHandleV1Id, ExtImageCopyCaptureSessionV1Id, JayScreencastId,
|
||||||
|
|
@ -55,6 +49,8 @@ use {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
opaque!(ToplevelIdentifier, toplevel_identifier);
|
||||||
|
|
||||||
tree_id!(ToplevelNodeId);
|
tree_id!(ToplevelNodeId);
|
||||||
|
|
||||||
pub trait ToplevelNode: ToplevelNodeBase {
|
pub trait ToplevelNode: ToplevelNodeBase {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
pub mod activation_token;
|
|
||||||
pub mod array;
|
pub mod array;
|
||||||
pub mod array_to_tuple;
|
pub mod array_to_tuple;
|
||||||
pub mod asyncevent;
|
pub mod asyncevent;
|
||||||
|
|
@ -60,7 +59,6 @@ pub mod string_ext;
|
||||||
pub mod syncqueue;
|
pub mod syncqueue;
|
||||||
pub mod threshold_counter;
|
pub mod threshold_counter;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod toplevel_identifier;
|
|
||||||
pub mod tri;
|
pub mod tri;
|
||||||
pub mod unlink_on_drop;
|
pub mod unlink_on_drop;
|
||||||
pub mod vec_ext;
|
pub mod vec_ext;
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
use {
|
|
||||||
crate::utils::opaque::{OPAQUE_LEN, Opaque, OpaqueError, opaque},
|
|
||||||
arrayvec::ArrayString,
|
|
||||||
std::{
|
|
||||||
fmt::{Display, Formatter},
|
|
||||||
str::FromStr,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
|
|
||||||
pub struct ActivationToken(Opaque);
|
|
||||||
|
|
||||||
pub fn activation_token() -> ActivationToken {
|
|
||||||
ActivationToken(opaque())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActivationToken {
|
|
||||||
pub fn to_string(self) -> ArrayString<OPAQUE_LEN> {
|
|
||||||
self.0.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ActivationToken {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
self.0.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ActivationToken {
|
|
||||||
type Err = OpaqueError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(Self(s.parse()?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use {
|
use {
|
||||||
|
crate::utils::array,
|
||||||
arrayvec::ArrayString,
|
arrayvec::ArrayString,
|
||||||
rand::{RngExt, rng},
|
rand::{RngExt, rng},
|
||||||
serde::{Deserialize, Deserializer, Serialize, Serializer, de},
|
serde::{Deserialize, Deserializer, Serialize, Serializer, de},
|
||||||
|
|
@ -10,17 +11,19 @@ use {
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct Opaque {
|
pub struct Opaque {
|
||||||
lo: u64,
|
v: [u64; 3],
|
||||||
hi: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opaque() -> Opaque {
|
pub fn opaque() -> Opaque {
|
||||||
let mut rng = rng();
|
let mut rng = rng();
|
||||||
Opaque {
|
Opaque {
|
||||||
lo: rng.random(),
|
v: array::from_fn(|_| rng.random()),
|
||||||
hi: rng.random(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,8 +38,9 @@ impl Opaque {
|
||||||
|
|
||||||
impl Display for Opaque {
|
impl Display for Opaque {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{:016x}", self.hi)?;
|
write!(f, "{:016x}", self.v[2])?;
|
||||||
write!(f, "{:016x}", self.lo)?;
|
write!(f, "{:016x}", self.v[1])?;
|
||||||
|
write!(f, "{:016x}", self.v[0])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,24 +76,32 @@ impl FromStr for Opaque {
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
if s.len() != OPAQUE_LEN {
|
if s.len() != OPAQUE_LEN {
|
||||||
return Err(OpaqueError::InvalidLength);
|
return Err(OpaqueError::InvalidStringLength);
|
||||||
}
|
}
|
||||||
if !s.is_char_boundary(OPAQUE_LEN / 2) {
|
if !s.is_char_boundary(OPAQUE_SEGMENT) {
|
||||||
return Err(OpaqueError::NotAscii);
|
return Err(OpaqueError::NotAscii);
|
||||||
}
|
}
|
||||||
let (hi, lo) = s.split_at(OPAQUE_LEN / 2);
|
let (a, s) = s.split_at(OPAQUE_SEGMENT);
|
||||||
let hi = u64::from_str_radix(hi, 16).map_err(OpaqueError::Parse)?;
|
if !s.is_char_boundary(OPAQUE_SEGMENT) {
|
||||||
let lo = u64::from_str_radix(lo, 16).map_err(OpaqueError::Parse)?;
|
return Err(OpaqueError::NotAscii);
|
||||||
Ok(Self { lo, hi })
|
}
|
||||||
|
let (b, c) = s.split_at(OPAQUE_SEGMENT);
|
||||||
|
let v = [
|
||||||
|
u64::from_str_radix(c, 16).map_err(OpaqueError::Parse)?,
|
||||||
|
u64::from_str_radix(b, 16).map_err(OpaqueError::Parse)?,
|
||||||
|
u64::from_str_radix(a, 16).map_err(OpaqueError::Parse)?,
|
||||||
|
];
|
||||||
|
Ok(Self { v })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const OPAQUE_LEN: usize = 32;
|
pub const OPAQUE_LEN: usize = 48;
|
||||||
|
const OPAQUE_SEGMENT: usize = OPAQUE_LEN / 3;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum OpaqueError {
|
pub enum OpaqueError {
|
||||||
#[error("The string is not exactly 32 bytes long")]
|
#[error("The string is not exactly {OPAQUE_LEN} bytes long")]
|
||||||
InvalidLength,
|
InvalidStringLength,
|
||||||
#[error("The string is not ascii")]
|
#[error("The string is not ascii")]
|
||||||
NotAscii,
|
NotAscii,
|
||||||
#[error("Could not parse the string as a hex number")]
|
#[error("Could not parse the string as a hex number")]
|
||||||
|
|
|
||||||
12
src/utils/opaque/tests.rs
Normal file
12
src/utils/opaque/tests.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
use {
|
||||||
|
crate::utils::opaque::{Opaque, opaque},
|
||||||
|
std::str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip() {
|
||||||
|
let v1 = opaque();
|
||||||
|
let s = v1.to_string();
|
||||||
|
let v2 = Opaque::from_str(&s).unwrap();
|
||||||
|
assert_eq!(v1, v2);
|
||||||
|
}
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
use {
|
|
||||||
crate::utils::{
|
|
||||||
clonecell::UnsafeCellCloneSafe,
|
|
||||||
opaque::{OPAQUE_LEN, Opaque, OpaqueError, opaque},
|
|
||||||
},
|
|
||||||
arrayvec::ArrayString,
|
|
||||||
std::{
|
|
||||||
fmt::{Display, Formatter},
|
|
||||||
str::FromStr,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, Ord, PartialOrd)]
|
|
||||||
pub struct ToplevelIdentifier(Opaque);
|
|
||||||
|
|
||||||
unsafe impl UnsafeCellCloneSafe for ToplevelIdentifier {}
|
|
||||||
|
|
||||||
pub fn toplevel_identifier() -> ToplevelIdentifier {
|
|
||||||
ToplevelIdentifier(opaque())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToplevelIdentifier {
|
|
||||||
pub fn to_string(self) -> ArrayString<OPAQUE_LEN> {
|
|
||||||
self.0.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ToplevelIdentifier {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
self.0.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ToplevelIdentifier {
|
|
||||||
type Err = OpaqueError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(Self(s.parse()?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue