Skip to main content

kasane_logic/spatial_id/single_id/
constructor.rs

1use crate::SingleId;
2
3use crate::{
4    SpatialIdError, TemporalId,
5    error::Error,
6    spatial_id::constants::{F_MAX, F_MIN, MAX_ZOOM_LEVEL, XY_MAX},
7};
8
9impl SingleId {
10    /// 指定された値から [`SingleId`] を作成する。このコンストラクタは、与えられた `z`, `f`, `x`, `y` が  各ズームレベルにおける範囲内にあるかを検証し、範囲外の場合は [`Error`] を返す。
11    ///
12    /// # パラメータ
13    /// * `z` — ズームレベル(0–[MAX_ZOOM_LEVEL]の範囲が有効)
14    /// * `f` — Fインデックス(鉛直方向)
15    /// * `x` — Xインデックス(東西方向)
16    /// * `y` — Yインデックス(南北方向)
17    ///
18    /// # バリデーション
19    /// - `z` が [`MAX_ZOOM_LEVEL`] を超える場合、[`SpatialIdError::ZOutOfRange`] を返す。
20    /// - `f` がズームレベル `z` に対する `F_MIN[z]..=F_MAX[z]` の範囲外の場合、
21    ///   [`SpatialIdError::FOutOfRange`] を返す。
22    /// - `x` または `y` が `0..=XY_MAX[z]` の範囲外の場合、
23    ///   それぞれ [`SpatialIdError::XOutOfRange`]、[`SpatialIdError::YOutOfRange`] を返す。
24    ///
25    ///
26    /// IDの作成:
27    /// ```no_run
28    /// # use kasane_logic::SingleId;
29    /// let id = SingleId::new(5, 3, 2, 10).unwrap();
30    /// assert_eq!(id.to_string(), "5/3/2/10".to_string());
31    /// ```
32    ///
33    /// 次元の範囲外の検知:
34    /// ```no_run
35    /// # use kasane_logic::SingleId;
36    /// # use kasane_logic::SpatialIdError;
37    /// let id = SingleId::new(3, 3, 2, 10);
38    /// assert_eq!(id, Err(SpatialIdError::YOutOfRange{z:3,y:10}.into()));
39    /// ```
40    ///
41    /// ズームレベルの範囲外の検知:
42    /// ```
43    /// # use kasane_logic::SingleId;
44    /// # use kasane_logic::SpatialIdError;
45    /// let id = SingleId::new(68, 3, 2, 10);
46    /// assert_eq!(id, Err(SpatialIdError::ZOutOfRange { z:68 }.into()));
47    /// ```
48    pub fn new(z: u8, f: i32, x: u32, y: u32) -> Result<SingleId, Error> {
49        if z > MAX_ZOOM_LEVEL as u8 {
50            return Err(SpatialIdError::ZOutOfRange { z }.into());
51        }
52
53        let f_min = F_MIN[z as usize];
54        let f_max = F_MAX[z as usize];
55        let xy_max = XY_MAX[z as usize];
56
57        if f < f_min || f > f_max {
58            return Err(SpatialIdError::FOutOfRange { f, z }.into());
59        }
60        if x > xy_max {
61            return Err(SpatialIdError::XOutOfRange { x, z }.into());
62        }
63        if y > xy_max {
64            return Err(SpatialIdError::YOutOfRange { y, z }.into());
65        }
66
67        Ok(SingleId {
68            z,
69            f,
70            x,
71            y,
72            temporal_id: TemporalId::WHOLE,
73        })
74    }
75
76    /// 検証を行わずに [`SingleId`] を作成する。
77    ///
78    /// この関数は [`SingleId::new`] と異なり、与えられた `z`, `f`, `x`, `y` に対して一切の範囲チェックや整合性チェックを行わない。そのため、高速に ID を生成できるが、**不正なパラメータを与えた場合の動作は未定義である**。
79    ///
80    /// # 注意
81    /// 呼び出し側は、以下をすべて満たすことを保証しなければならない。
82    ///
83    /// * `z` が有効なズームレベル(0–[MAX_ZOOM_LEVEL])であること
84    /// * `f` が与えられた `z` に応じて `F_MIN[z]..=F_MAX[z]` の範囲内であること
85    /// * `x` および `y` が `0..=XY_MAX[z]` の範囲内であること
86    ///
87    /// これらが保証されない場合、パニック・不正メモリアクセス・未定義動作を引き起こす可能性がある。
88    ///
89    /// ```
90    /// # use kasane_logic::SingleId;
91    /// // パラメータが妥当であることを呼び出し側が保証する必要がある
92    /// let id = unsafe { SingleId::new_unchecked(5, 3, 2, 10) };
93    ///
94    /// assert_eq!(id.z(), 5u8);
95    /// assert_eq!(id.f(), 3i32);
96    /// assert_eq!(id.x(), 2u32);
97    /// assert_eq!(id.y(), 10u32);
98    /// ```
99    pub unsafe fn new_unchecked(z: u8, f: i32, x: u32, y: u32) -> SingleId {
100        SingleId {
101            z,
102            f,
103            x,
104            y,
105            temporal_id: TemporalId::WHOLE,
106        }
107    }
108
109    /// 指定された値から時間情報を指定した [`SingleId`] を作成する。このコンストラクタは、与えられた `z`, `f`, `x`, `y` が  各ズームレベルにおける範囲内にあるかを検証し、範囲外の場合は [`Error`] を返す。
110    ///
111    /// # パラメータ
112    /// * `z` — ズームレベル(0–[MAX_ZOOM_LEVEL]の範囲が有効)
113    /// * `f` — Fインデックス(鉛直方向)
114    /// * `x` — Xインデックス(東西方向)
115    /// * `y` — Yインデックス(南北方向)
116    /// * `temporal_id` — [TemporalId](時間ID)
117    ///
118    /// # バリデーション
119    /// - `z` が [`MAX_ZOOM_LEVEL`] を超える場合、[`SpatialIdError::ZOutOfRange`] を返す。
120    /// - `f` がズームレベル `z` に対する `F_MIN[z]..=F_MAX[z]` の範囲外の場合、
121    ///   [`SpatialIdError::FOutOfRange`] を返す。
122    /// - `x` または `y` が `0..=XY_MAX[z]` の範囲外の場合、
123    ///   それぞれ [`SpatialIdError::XOutOfRange`]、[`SpatialIdError::YOutOfRange`] を返す。
124    ///
125    ///
126    /// IDの作成:
127    /// ```no_run
128    /// # use kasane_logic::{SingleId,TemporalId};
129    /// //時間IDの作成
130    /// let temporal_id = TemporalId::new(60, [1,1]).unwrap();
131    ///
132    /// let id = SingleId::new_with_temporal(5, 3, 2, 10,temporal_id).unwrap();
133    /// assert_eq!(id.to_string(), "5/3/2/10_60/1:1".to_string());
134    /// ```
135    #[cfg(feature = "temporal_id")]
136    pub fn new_with_temporal(
137        z: u8,
138        f: i32,
139        x: u32,
140        y: u32,
141        temporal_id: TemporalId,
142    ) -> Result<SingleId, Error> {
143        if z > MAX_ZOOM_LEVEL as u8 {
144            return Err(SpatialIdError::ZOutOfRange { z }.into());
145        }
146
147        let f_min = F_MIN[z as usize];
148        let f_max = F_MAX[z as usize];
149        let xy_max = XY_MAX[z as usize];
150
151        if f < f_min || f > f_max {
152            return Err(SpatialIdError::FOutOfRange { f, z }.into());
153        }
154        if x > xy_max {
155            return Err(SpatialIdError::XOutOfRange { x, z }.into());
156        }
157        if y > xy_max {
158            return Err(SpatialIdError::YOutOfRange { y, z }.into());
159        }
160
161        Ok(SingleId {
162            z,
163            f,
164            x,
165            y,
166
167            temporal_id,
168        })
169    }
170
171    /// 検証を行わずに 時間情報を指定した[`SingleId`] を作成する。
172    ///
173    /// この関数は [`SingleId::new`] と異なり、与えられた `z`, `f`, `x`, `y` に対して一切の範囲チェックや整合性チェックを行わない。そのため、高速に ID を生成できるが、**不正なパラメータを与えた場合の動作は未定義である**。
174    ///
175    /// # 注意
176    /// 呼び出し側は、以下をすべて満たすことを保証しなければならない。
177    ///
178    /// * `z` が有効なズームレベル(0–[MAX_ZOOM_LEVEL])であること
179    /// * `f` が与えられた `z` に応じて `F_MIN[z]..=F_MAX[z]` の範囲内であること
180    /// * `x` および `y` が `0..=XY_MAX[z]` の範囲内であること
181    ///
182    /// これらが保証されない場合、パニック・不正メモリアクセス・未定義動作を引き起こす可能性がある。
183    ///
184    /// ```
185    /// # use kasane_logic::{SingleId,TemporalId};
186    /// //時間IDの作成
187    /// let temporal_id = TemporalId::new(60, [1,1]).unwrap();
188    ///
189    /// // パラメータが妥当であることを呼び出し側が保証する必要がある
190    /// let id = unsafe { SingleId::new_with_temporal_unchecked(5, 3, 2, 10,temporal_id) };
191    ///
192    /// assert_eq!(id.z(), 5u8);
193    /// assert_eq!(id.f(), 3i32);
194    /// assert_eq!(id.x(), 2u32);
195    /// assert_eq!(id.y(), 10u32);
196    /// ```
197    #[cfg(feature = "temporal_id")]
198    pub unsafe fn new_with_temporal_unchecked(
199        z: u8,
200        f: i32,
201        x: u32,
202        y: u32,
203        temporal_id: TemporalId,
204    ) -> SingleId {
205        SingleId {
206            z,
207            f,
208            x,
209            y,
210            temporal_id,
211        }
212    }
213}