Minor fixes

This commit is contained in:
Austen Adler 2023-03-16 01:18:59 -04:00
parent 2d0bdce184
commit 22549f378a
3 changed files with 59 additions and 42 deletions

View File

@ -31,8 +31,8 @@ pub const V0_MIN_NUMBER: u32 = 1024;
#[derive(Error, Debug, Eq, PartialEq)]
pub enum Error {
/// The given word is not in the wordlist
#[error("Word does not exist: {0}")]
WordDoesNotExist(String),
#[error("Words do not exist: {0:?}")]
WordsDoNotExist(Vec<String>),
/// The encoded version bit is not supported by this version of the crate
#[error("Unimplemented version: {0}")]
UnimplementedVersion(u8),
@ -43,7 +43,7 @@ pub enum Error {
#[error("The string given is not ascii")]
NonAscii,
/// The number of components given to decode is incorrect
#[error("Wrong number of components")]
#[error("Need one number and three words")]
WrongComponentCount,
/// No number component was found
///
@ -58,6 +58,9 @@ pub enum Error {
/// This is the case when either lat or lon is f64::NAN
#[error("Invalid latitude or longitude")]
NaNLatLng,
#[error("Words cannot be repeated")]
RepeatedWords,
}
#[allow(clippy::doc_markdown)]
@ -131,7 +134,6 @@ impl Address<'_> {
/// This will return [`Error::NaNLatLng`] when the latitude or longitude are not valid
///
/// See [`Error::NaNLatLng`] for the valid values
pub fn from_lat_lon(lat: f64, lon: f64) -> Result<Self, Error> {
let cellid = conversions::lat_lon_to_cellid(lat, lon)?;
@ -160,21 +162,39 @@ impl Address<'_> {
return Err(Error::WrongComponentCount);
}
// Convert each word component into a word, returning an error if any do not match
let words = TryInto::<[&'static Word; 3]>::try_into(
word_components
.iter()
.map(|w| {
words::get_word(w).ok_or_else(|| Error::WordDoesNotExist((*w).to_string()))
})
.collect::<Result<Vec<&'static Word>, Error>>()?,
)
// This unwrap is okay because we just checked to make sure the number of word components was 3
.unwrap();
// Check that each word exists
let mut errors = vec![];
let mut words = vec![];
for word in word_components {
match words::get_word(word) {
Some(w) => words.push(w),
None => errors.push(word.to_ascii_uppercase()),
}
}
if !errors.is_empty() {
return Err(Error::WordsDoNotExist(errors));
}
// Check that each word is not repeated
// TODO: This will be handled by the call to get_words_multi later
{
let mut word_numbers: Vec<u16> = words.iter().map(|w| w.number).collect();
word_numbers.sort();
let prev_len = word_numbers.len();
word_numbers.dedup();
let cur_len = word_numbers.len();
if prev_len != cur_len {
return Err(Error::RepeatedWords);
}
}
Ok(Self {
number,
words,
// This unwrap is okay because we just checked to make sure the number of word components was 3
words: TryInto::<[&'static Word; 3]>::try_into(words).unwrap(),
version: Version::V0,
})
}
@ -202,17 +222,6 @@ impl Address<'_> {
}
}
/// Extracts a version number from a number
///
/// The version number is set by the two bits 11 and 12
// TODO: impl TryFrom ?
// const fn extract_version(number: Number) -> Result<Version, Error> {
// match ((number >> 10) & 0b11) as u8 {
// 0 => Ok(Version::V0),
// v => Err(Error::UnimplementedVersion(v)),
// }
// }
impl Display for Address<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
@ -243,18 +252,6 @@ mod tests {
};
}
// #[test]
// fn test_extract_version() {
// assert_eq!(extract_version(0b0000_0000_0000), 0b00);
// assert_eq!(extract_version(0b1100_0000_0000), 0b11);
// assert_eq!(extract_version(0b0100_0000_0000), 0b01);
// assert_eq!(extract_version(0b1000_0000_0000), 0b10);
// assert_eq!(extract_version(0b11 << 10), 0b11);
// assert_eq!(extract_version(0b00 << 10), 0b00);
// assert_eq!(extract_version(0b10 << 10), 0b10);
// assert_eq!(extract_version(0b01 << 10), 0b01);
// }
#[test]
fn test_address_from_str() {
for i in &[

View File

@ -24,9 +24,9 @@ placeholder="Enter address"></Svelecte>
</script>
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="username"> Address </label>
<label class="text-gray-700 text-sm font-bold mb-2" for="username">Address</label>
<input
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline w-96"
type="text"
bind:value
placeholder="Address"

View File

@ -105,10 +105,30 @@
{#await init()}
<p class="text-lg js-only">Loading WebAssembly module...</p>
{:then}
<p>Current cursor: {addr.address} ({addr.latLon}) => ({latlng.lat}, {latlng.lng})</p>
<p>Address: <span class="font-bold">{addr.address}</span></p>
<p class="text-sm">({addr.latLon}) => ({latlng.lat}, {latlng.lng})</p>
<AddressInput bind:value={addrInputValue} on:input={input} />
<div class="mb-4">
<label class="text-gray-700 text-sm font-bold mb-2" for="username">Latitude</label>
<input
class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
disabled
type="text"
bind:value={latlng.lat}
placeholder="0.00"
/>
<label class="text-gray-700 text-sm font-bold mb-2" for="username">Longitude</label>
<input
class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
disabled
type="text"
bind:value={latlng.lng}
placeholder="0.00"
/>
</div>
<Map bind:map {onMapClick} />
{:catch message}
<Error {message}>Could not start core module</Error>