|
@@ -423,6 +423,9 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
|
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
|
}
|
|
}
|
|
|
i = start;
|
|
i = start;
|
|
|
|
|
+ if piece_pointer > 6 {
|
|
|
|
|
+ return Err(ParseError::InvalidIpv6Address)
|
|
|
|
|
+ }
|
|
|
is_ip_v4 = true;
|
|
is_ip_v4 = true;
|
|
|
},
|
|
},
|
|
|
b':' => {
|
|
b':' => {
|
|
@@ -445,16 +448,24 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
|
|
|
if piece_pointer > 6 {
|
|
if piece_pointer > 6 {
|
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
|
}
|
|
}
|
|
|
- let mut dots_seen = 0;
|
|
|
|
|
|
|
+ let mut numbers_seen = 0;
|
|
|
while i < len {
|
|
while i < len {
|
|
|
- let mut value = None;
|
|
|
|
|
|
|
+ if numbers_seen > 0 {
|
|
|
|
|
+ if numbers_seen < 4 && (i < len && input[i] == b'.') {
|
|
|
|
|
+ i += 1
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return Err(ParseError::InvalidIpv6Address)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut ipv4_piece = None;
|
|
|
while i < len {
|
|
while i < len {
|
|
|
let digit = match input[i] {
|
|
let digit = match input[i] {
|
|
|
c @ b'0' ... b'9' => c - b'0',
|
|
c @ b'0' ... b'9' => c - b'0',
|
|
|
_ => break
|
|
_ => break
|
|
|
};
|
|
};
|
|
|
- match value {
|
|
|
|
|
- None => value = Some(digit as u16),
|
|
|
|
|
|
|
+ match ipv4_piece {
|
|
|
|
|
+ None => ipv4_piece = Some(digit as u16),
|
|
|
Some(0) => return Err(ParseError::InvalidIpv6Address), // No leading zero
|
|
Some(0) => return Err(ParseError::InvalidIpv6Address), // No leading zero
|
|
|
Some(ref mut v) => {
|
|
Some(ref mut v) => {
|
|
|
*v = *v * 10 + digit as u16;
|
|
*v = *v * 10 + digit as u16;
|
|
@@ -465,24 +476,28 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
|
|
|
}
|
|
}
|
|
|
i += 1;
|
|
i += 1;
|
|
|
}
|
|
}
|
|
|
- if dots_seen < 3 && !(i < len && input[i] == b'.') {
|
|
|
|
|
- return Err(ParseError::InvalidIpv6Address)
|
|
|
|
|
- }
|
|
|
|
|
- pieces[piece_pointer] = if let Some(v) = value {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ pieces[piece_pointer] = if let Some(v) = ipv4_piece {
|
|
|
pieces[piece_pointer] * 0x100 + v
|
|
pieces[piece_pointer] * 0x100 + v
|
|
|
} else {
|
|
} else {
|
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
return Err(ParseError::InvalidIpv6Address)
|
|
|
};
|
|
};
|
|
|
- if dots_seen == 1 || dots_seen == 3 {
|
|
|
|
|
|
|
+ numbers_seen += 1;
|
|
|
|
|
+
|
|
|
|
|
+ if numbers_seen == 2 || numbers_seen == 4 {
|
|
|
piece_pointer += 1;
|
|
piece_pointer += 1;
|
|
|
}
|
|
}
|
|
|
- i += 1;
|
|
|
|
|
- if dots_seen == 3 && i < len {
|
|
|
|
|
- return Err(ParseError::InvalidIpv6Address)
|
|
|
|
|
- }
|
|
|
|
|
- dots_seen += 1;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if numbers_seen != 4 {
|
|
|
|
|
+ return Err(ParseError::InvalidIpv6Address)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if i < len {
|
|
|
|
|
+ return Err(ParseError::InvalidIpv6Address)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
match compress_pointer {
|
|
match compress_pointer {
|
|
|
Some(compress_pointer) => {
|
|
Some(compress_pointer) => {
|
|
|
let mut swaps = piece_pointer - compress_pointer;
|
|
let mut swaps = piece_pointer - compress_pointer;
|