// SPDX-FileCopyrightText: 2022 Thomas Kramer // // SPDX-License-Identifier: GPL-3.0-or-later //! Types which help to use the type system to distinguish between //! data in canonical and non-canonical form. //! //! Tree data structures for example might be efficiently comparable if they are //! in a canonical form, but not if they are in a non-canonical form. //! //! Note: This is an experiment for now. use std::ops::Deref; /// Mark datatype to have canonical form. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Canonical; /// Mark datatype to have potentially non-canonical form. #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct NonCanonical; pub trait CanonicalMarker: Clone { fn is_canonical() -> bool; } impl CanonicalMarker for Canonical { fn is_canonical() -> bool { true } } impl CanonicalMarker for NonCanonical { fn is_canonical() -> bool { false } } /// Wrapper which 'guarantees' that the content has canonical form pub struct Ca { data: T, } impl Deref for Ca { type Target = T; fn deref(&self) -> &Self::Target { &self.data } } pub trait WithCanonicalForm { type NonCanonical: WithCanonicalForm; fn is_canonical(&self) -> bool; fn into_canonical_form(self) -> Ca; }