Skip to content

Commit b2ca83a

Browse files
committed
switch to ipv6, add monotonic_mapping tests
1 parent b9b9135 commit b2ca83a

File tree

7 files changed

+97
-69
lines changed

7 files changed

+97
-69
lines changed

fastfield_codecs/src/monotonic_mapping.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,30 @@ impl MonotonicallyMappableToU64 for f64 {
202202

203203
#[cfg(test)]
204204
mod tests {
205+
205206
use super::*;
206207

207208
#[test]
208209
fn strictly_monotonic_test() {
210+
// identity mapping
211+
test_round_trip(&StrictlyMonotonicMappingToInternal::<u64>::new(), 100u64);
212+
// round trip to i64
213+
test_round_trip(&StrictlyMonotonicMappingToInternal::<i64>::new(), 100u64);
214+
// identity mapping
215+
test_round_trip(&StrictlyMonotonicMappingToInternal::<u128>::new(), 100u128);
216+
217+
// base value to i64 round trip
218+
let mapping = StrictlyMonotonicMappingToInternalBaseval::new(100);
219+
test_round_trip::<_, _, u64>(&mapping, 100i64);
220+
// base value and gcd to u64 round trip
209221
let mapping = StrictlyMonotonicMappingToInternalGCDBaseval::new(10, 100);
222+
test_round_trip::<_, _, u64>(&mapping, 100u64);
223+
}
210224

211-
let test_val = 100u64;
212-
assert_eq!(mapping.mapping(test_val), 0);
225+
fn test_round_trip<T: StrictlyMonotonicFn<K, L>, K: std::fmt::Debug + Eq + Copy, L>(
226+
mapping: &T,
227+
test_val: K,
228+
) {
213229
assert_eq!(mapping.inverse(mapping.mapping(test_val)), test_val);
214230
}
215231
}

fastfield_codecs/src/monotonic_mapping_u128.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::net::{IpAddr, Ipv6Addr};
1+
use std::net::Ipv6Addr;
22

33
pub trait MonotonicallyMappableToU128: 'static + PartialOrd + Copy + Send + Sync {
44
/// Converts a value to u128.
@@ -23,20 +23,16 @@ impl MonotonicallyMappableToU128 for u128 {
2323
}
2424
}
2525

26-
impl MonotonicallyMappableToU128 for IpAddr {
26+
impl MonotonicallyMappableToU128 for Ipv6Addr {
2727
fn to_u128(self) -> u128 {
2828
ip_to_u128(self)
2929
}
3030

3131
fn from_u128(val: u128) -> Self {
32-
IpAddr::from(val.to_be_bytes())
32+
Ipv6Addr::from(val.to_be_bytes())
3333
}
3434
}
3535

36-
fn ip_to_u128(ip_addr: IpAddr) -> u128 {
37-
let ip_addr_v6: Ipv6Addr = match ip_addr {
38-
IpAddr::V4(v4) => v4.to_ipv6_mapped(),
39-
IpAddr::V6(v6) => v6,
40-
};
41-
u128::from_be_bytes(ip_addr_v6.octets())
36+
fn ip_to_u128(ip_addr: Ipv6Addr) -> u128 {
37+
u128::from_be_bytes(ip_addr.octets())
4238
}

src/fastfield/readers.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::net::IpAddr;
1+
use std::net::Ipv6Addr;
22
use std::sync::Arc;
33

44
use fastfield_codecs::{open, open_u128, Column};
@@ -155,18 +155,21 @@ impl FastFieldReaders {
155155
pub fn ip_addr(&self, field: Field) -> crate::Result<Arc<dyn Column<Ipv6Addr>>> {
156156
self.check_type(field, FastType::U128, Cardinality::SingleValue)?;
157157
let bytes = self.fast_field_data(field, 0)?.read_bytes()?;
158-
Ok(open_u128::<IpAddr>(bytes)?)
158+
Ok(open_u128::<Ipv6Addr>(bytes)?)
159159
}
160160

161161
/// Returns the `ip` fast field reader reader associated to `field`.
162162
///
163163
/// If `field` is not a u128 fast field, this method returns an Error.
164-
pub fn ip_addrs(&self, field: Field) -> crate::Result<MultiValuedU128FastFieldReader<IpAddr>> {
164+
pub fn ip_addrs(
165+
&self,
166+
field: Field,
167+
) -> crate::Result<MultiValuedU128FastFieldReader<Ipv6Addr>> {
165168
self.check_type(field, FastType::U128, Cardinality::MultiValues)?;
166169
let idx_reader: Arc<dyn Column<u64>> = self.typed_fast_field_reader(field)?;
167170

168171
let bytes = self.fast_field_data(field, 1)?.read_bytes()?;
169-
let vals_reader = open_u128::<IpAddr>(bytes)?;
172+
let vals_reader = open_u128::<Ipv6Addr>(bytes)?;
170173

171174
Ok(MultiValuedU128FastFieldReader::open(
172175
idx_reader,

src/indexer/index_writer.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ impl Drop for IndexWriter {
803803
#[cfg(test)]
804804
mod tests {
805805
use std::collections::{HashMap, HashSet};
806-
use std::net::IpAddr;
806+
use std::net::Ipv6Addr;
807807

808808
use fastfield_codecs::MonotonicallyMappableToU128;
809809
use proptest::prelude::*;
@@ -1655,7 +1655,7 @@ mod tests {
16551655
match op {
16561656
IndexingOp::AddDoc { id } => {
16571657
let facet = Facet::from(&("/cola/".to_string() + &id.to_string()));
1658-
let ip_from_id = IpAddr::from_u128(id as u128);
1658+
let ip_from_id = Ipv6Addr::from_u128(id as u128);
16591659

16601660
if id % 3 == 0 {
16611661
// every 3rd doc has no ip field
@@ -1772,14 +1772,14 @@ mod tests {
17721772
);
17731773

17741774
// Load all ips addr
1775-
let ips: HashSet<IpAddr> = searcher
1775+
let ips: HashSet<Ipv6Addr> = searcher
17761776
.segment_readers()
17771777
.iter()
17781778
.flat_map(|segment_reader| {
17791779
let ff_reader = segment_reader.fast_fields().ip_addr(ip_field).unwrap();
17801780
segment_reader.doc_ids_alive().flat_map(move |doc| {
17811781
let val = ff_reader.get_val(doc as u64);
1782-
if val == IpAddr::from_u128(0) {
1782+
if val == Ipv6Addr::from_u128(0) {
17831783
// TODO Fix null handling
17841784
None
17851785
} else {
@@ -1795,7 +1795,7 @@ mod tests {
17951795
if id % 3 == 0 {
17961796
None
17971797
} else {
1798-
Some(IpAddr::from_u128(*id as u128))
1798+
Some(Ipv6Addr::from_u128(*id as u128))
17991799
}
18001800
})
18011801
.collect::<HashSet<_>>();
@@ -1807,11 +1807,11 @@ mod tests {
18071807
if id % 3 == 0 {
18081808
None
18091809
} else {
1810-
Some(IpAddr::from_u128(*id as u128))
1810+
Some(Ipv6Addr::from_u128(*id as u128))
18111811
}
18121812
})
18131813
.collect::<HashSet<_>>();
1814-
let ips: HashSet<IpAddr> = searcher
1814+
let ips: HashSet<Ipv6Addr> = searcher
18151815
.segment_readers()
18161816
.iter()
18171817
.flat_map(|segment_reader| {

src/schema/document.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::{HashMap, HashSet};
22
use std::io::{self, Read, Write};
33
use std::mem;
4-
use std::net::IpAddr;
4+
use std::net::Ipv6Addr;
55

66
use common::{BinarySerializable, VInt};
77

@@ -76,7 +76,9 @@ impl Document {
7676

7777
/// Adding a facet to the document.
7878
pub fn add_facet<F>(&mut self, field: Field, path: F)
79-
where Facet: From<F> {
79+
where
80+
Facet: From<F>,
81+
{
8082
let facet = Facet::from(path);
8183
let value = Value::Facet(facet);
8284
self.add_field_value(field, value);
@@ -98,8 +100,8 @@ impl Document {
98100
self.add_field_value(field, value);
99101
}
100102

101-
/// Add a IP address field
102-
pub fn add_ip_addr(&mut self, field: Field, value: IpAddrV6) {
103+
/// Add a IP address field. Internally only Ipv6Addr is used.
104+
pub fn add_ip_addr(&mut self, field: Field, value: Ipv6Addr) {
103105
self.add_field_value(field, value);
104106
}
105107

src/schema/field_type.rs

+40-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::net::IpAddr;
1+
use std::net::{IpAddr, Ipv6Addr};
22
use std::str::FromStr;
33

44
use serde::{Deserialize, Serialize};
@@ -320,43 +320,50 @@ impl FieldType {
320320
/// target field is a `Str`, this method will return an Error.
321321
pub fn value_from_json(&self, json: JsonValue) -> Result<Value, ValueParsingError> {
322322
match json {
323-
JsonValue::String(field_text) => match self {
324-
FieldType::Date(_) => {
325-
let dt_with_fixed_tz =
326-
OffsetDateTime::parse(&field_text, &Rfc3339).map_err(|_err| {
327-
ValueParsingError::TypeError {
323+
JsonValue::String(field_text) => {
324+
match self {
325+
FieldType::Date(_) => {
326+
let dt_with_fixed_tz = OffsetDateTime::parse(&field_text, &Rfc3339)
327+
.map_err(|_err| ValueParsingError::TypeError {
328328
expected: "rfc3339 format",
329329
json: JsonValue::String(field_text),
330+
})?;
331+
Ok(DateTime::from_utc(dt_with_fixed_tz).into())
332+
}
333+
FieldType::Str(_) => Ok(Value::Str(field_text)),
334+
FieldType::U64(_) | FieldType::I64(_) | FieldType::F64(_) => {
335+
Err(ValueParsingError::TypeError {
336+
expected: "an integer",
337+
json: JsonValue::String(field_text),
338+
})
339+
}
340+
FieldType::Bool(_) => Err(ValueParsingError::TypeError {
341+
expected: "a boolean",
342+
json: JsonValue::String(field_text),
343+
}),
344+
FieldType::Facet(_) => Ok(Value::Facet(Facet::from(&field_text))),
345+
FieldType::Bytes(_) => base64::decode(&field_text)
346+
.map(Value::Bytes)
347+
.map_err(|_| ValueParsingError::InvalidBase64 { base64: field_text }),
348+
FieldType::JsonObject(_) => Err(ValueParsingError::TypeError {
349+
expected: "a json object",
350+
json: JsonValue::String(field_text),
351+
}),
352+
FieldType::IpAddr(_) => {
353+
let ip_addr: IpAddr = IpAddr::from_str(&field_text).map_err(|err| {
354+
ValueParsingError::ParseError {
355+
error: err.to_string(),
356+
json: JsonValue::String(field_text),
330357
}
331358
})?;
332-
Ok(DateTime::from_utc(dt_with_fixed_tz).into())
333-
}
334-
FieldType::Str(_) => Ok(Value::Str(field_text)),
335-
FieldType::U64(_) | FieldType::I64(_) | FieldType::F64(_) => {
336-
Err(ValueParsingError::TypeError {
337-
expected: "an integer",
338-
json: JsonValue::String(field_text),
339-
})
359+
let ip_addr_v6: Ipv6Addr = match ip_addr {
360+
IpAddr::V4(v4) => v4.to_ipv6_mapped(),
361+
IpAddr::V6(v6) => v6,
362+
};
363+
Ok(Value::IpAddr(ip_addr_v6))
364+
}
340365
}
341-
FieldType::Bool(_) => Err(ValueParsingError::TypeError {
342-
expected: "a boolean",
343-
json: JsonValue::String(field_text),
344-
}),
345-
FieldType::Facet(_) => Ok(Value::Facet(Facet::from(&field_text))),
346-
FieldType::Bytes(_) => base64::decode(&field_text)
347-
.map(Value::Bytes)
348-
.map_err(|_| ValueParsingError::InvalidBase64 { base64: field_text }),
349-
FieldType::JsonObject(_) => Err(ValueParsingError::TypeError {
350-
expected: "a json object",
351-
json: JsonValue::String(field_text),
352-
}),
353-
FieldType::IpAddr(_) => Ok(Value::IpAddr(IpAddr::from_str(&field_text).map_err(
354-
|err| ValueParsingError::ParseError {
355-
error: err.to_string(),
356-
json: JsonValue::String(field_text),
357-
},
358-
)?)),
359-
},
366+
}
360367
JsonValue::Number(field_val_num) => match self {
361368
FieldType::I64(_) | FieldType::Date(_) => {
362369
if let Some(field_val_i64) = field_val_num.as_i64() {

src/schema/value.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::fmt;
2-
use std::net::IpAddr;
2+
use std::net::Ipv6Addr;
33

44
use serde::de::Visitor;
55
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -33,15 +33,17 @@ pub enum Value {
3333
Bytes(Vec<u8>),
3434
/// Json object value.
3535
JsonObject(serde_json::Map<String, serde_json::Value>),
36-
/// Ip Address value
37-
IpAddr(IpAddr),
36+
/// IpV6 Address. Internally there is no IpV4, it needs to be converted to `Ipv6Addr`.
37+
IpAddr(Ipv6Addr),
3838
}
3939

4040
impl Eq for Value {}
4141

4242
impl Serialize for Value {
4343
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44-
where S: Serializer {
44+
where
45+
S: Serializer,
46+
{
4547
match *self {
4648
Value::Str(ref v) => serializer.serialize_str(v),
4749
Value::PreTokStr(ref v) => v.serialize(serializer),
@@ -60,7 +62,9 @@ impl Serialize for Value {
6062

6163
impl<'de> Deserialize<'de> for Value {
6264
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
63-
where D: Deserializer<'de> {
65+
where
66+
D: Deserializer<'de>,
67+
{
6468
struct ValueVisitor;
6569

6670
impl<'de> Visitor<'de> for ValueVisitor {
@@ -208,7 +212,7 @@ impl Value {
208212

209213
/// Returns the ip addr, provided the value is of the `Ip` type.
210214
/// (Returns None if the value is not of the `Ip` type)
211-
pub fn as_ip_addr(&self) -> Option<IpAddr> {
215+
pub fn as_ip_addr(&self) -> Option<Ipv6Addr> {
212216
if let Value::IpAddr(val) = self {
213217
Some(*val)
214218
} else {
@@ -223,8 +227,8 @@ impl From<String> for Value {
223227
}
224228
}
225229

226-
impl From<IpAddr> for Value {
227-
fn from(v: IpAddr) -> Value {
230+
impl From<Ipv6Addr> for Value {
231+
fn from(v: Ipv6Addr) -> Value {
228232
Value::IpAddr(v)
229233
}
230234
}
@@ -308,7 +312,7 @@ impl From<serde_json::Value> for Value {
308312

309313
mod binary_serialize {
310314
use std::io::{self, Read, Write};
311-
use std::net::IpAddr;
315+
use std::net::Ipv6Addr;
312316

313317
use common::{f64_to_u64, u64_to_f64, BinarySerializable};
314318
use fastfield_codecs::MonotonicallyMappableToU128;
@@ -465,7 +469,7 @@ mod binary_serialize {
465469
}
466470
IP_CODE => {
467471
let value = u128::deserialize(reader)?;
468-
Ok(Value::IpAddr(IpAddr::from_u128(value)))
472+
Ok(Value::IpAddr(Ipv6Addr::from_u128(value)))
469473
}
470474

471475
_ => Err(io::Error::new(

0 commit comments

Comments
 (0)