linera_witty/memory_layout/
join_flat_layouts.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Joining of flat layouts of different variants of a `variant` type.
5//!
6//! When flattening `variant` types, a single flat layout must be obtained for the type by joining
7//! the flat layout of each variant. This means finding a flat type for each layout element to
8//! represent the flat type of any of the variants. See [`crate::primitive_types::JoinFlatTypes`]
9//! for more information on how flat types are joined.
10
11use either::Either;
12use frunk::{HCons, HNil};
13
14use crate::primitive_types::{FlatType, JoinFlatTypes};
15
16/// Allows converting between the current flat layout and the joined `Target` flat layout, which
17/// may be longer or have some elements wider than the current elements.
18pub trait JoinFlatLayouts<Target> {
19    /// Converts the current flat layout into a the joined `Target` flat layout.
20    fn into_joined(self) -> Target;
21
22    /// Converts from the joined `Target` flat layout into the current flat layout.
23    fn from_joined(joined: Target) -> Self;
24}
25
26impl JoinFlatLayouts<HNil> for HNil {
27    fn into_joined(self) -> HNil {
28        HNil
29    }
30
31    fn from_joined(_joined: HNil) -> Self {
32        HNil
33    }
34}
35
36impl<TargetHead, TargetTail> JoinFlatLayouts<HCons<TargetHead, TargetTail>> for HNil
37where
38    TargetHead: Default,
39    HNil: JoinFlatLayouts<TargetTail>,
40{
41    fn into_joined(self) -> HCons<TargetHead, TargetTail> {
42        HCons {
43            head: TargetHead::default(),
44            tail: HNil.into_joined(),
45        }
46    }
47
48    fn from_joined(_joined: HCons<TargetHead, TargetTail>) -> Self {
49        HNil
50    }
51}
52
53impl<SourceHead, SourceTail, TargetHead, TargetTail> JoinFlatLayouts<HCons<TargetHead, TargetTail>>
54    for HCons<SourceHead, SourceTail>
55where
56    SourceHead: FlatType,
57    TargetHead: FlatType,
58    Either<SourceHead, TargetHead>: JoinFlatTypes<Flat = TargetHead>,
59    SourceTail: JoinFlatLayouts<TargetTail>,
60{
61    fn into_joined(self) -> HCons<TargetHead, TargetTail> {
62        HCons {
63            head: Either::Left(self.head).join(),
64            tail: self.tail.into_joined(),
65        }
66    }
67
68    fn from_joined(joined: HCons<TargetHead, TargetTail>) -> Self {
69        HCons {
70            head: joined.head.split_into(),
71            tail: SourceTail::from_joined(joined.tail),
72        }
73    }
74}