|
1 | 1 | //! Copyright The KCL Authors. All rights reserved.
|
2 | 2 |
|
| 3 | +use cidr::IpCidr; |
3 | 4 | use std::net::IpAddr;
|
4 | 5 | use std::net::Ipv4Addr;
|
5 | 6 | use std::net::Ipv6Addr;
|
@@ -475,19 +476,14 @@ pub extern "C-unwind" fn kclvm_net_parse_CIDR(
|
475 | 476 | let kwargs = ptr_as_ref(kwargs);
|
476 | 477 | let ctx = mut_ptr_as_ref(ctx);
|
477 | 478 |
|
478 |
| - if let Some(cidr) = get_call_arg_str(args, kwargs, 0, Some("cidr")) { |
479 |
| - let parts: Vec<&str> = cidr.split('/').collect(); |
480 |
| - if parts.len() == 2 { |
481 |
| - let ip = parts[0]; |
482 |
| - let mask = parts[1]; |
483 |
| - if let Ok(ip) = Ipv4Addr::from_str(ip) { |
484 |
| - if let Ok(mask) = mask.parse::<u8>() { |
485 |
| - let ip_value = ValueRef::str(ip.to_string().as_str()); |
486 |
| - let mask_value = ValueRef::int(mask as i64); |
487 |
| - return ValueRef::dict(Some(&[("ip", &ip_value), ("mask", &mask_value)])) |
488 |
| - .into_raw(ctx); |
489 |
| - } |
490 |
| - } |
| 479 | + if let Some(cidr) = get_call_arg(args, kwargs, 0, Some("cidr")) { |
| 480 | + if cidr.is_none() { |
| 481 | + return ValueRef::none().into_raw(ctx); |
| 482 | + } |
| 483 | + if let Ok(cidr) = IpCidr::from_str(&cidr.as_str()) { |
| 484 | + let ip = ValueRef::str(&cidr.first_address().to_string()); |
| 485 | + let mask = ValueRef::int(cidr.network_length().into()); |
| 486 | + return ValueRef::dict(Some(&[("ip", &ip), ("mask", &mask)])).into_raw(ctx); |
491 | 487 | }
|
492 | 488 | return ValueRef::dict(None).into_raw(ctx);
|
493 | 489 | }
|
@@ -934,4 +930,124 @@ mod test_net {
|
934 | 930 | );
|
935 | 931 | std::panic::set_hook(prev_hook);
|
936 | 932 | }
|
| 933 | + |
| 934 | + #[test] |
| 935 | + #[allow(non_snake_case)] |
| 936 | + fn test_parse_CIDR() { |
| 937 | + let cases = [ |
| 938 | + (ValueRef::none(), ValueRef::none()), |
| 939 | + ( |
| 940 | + ValueRef::str("0.0.0.0/0"), |
| 941 | + ValueRef::dict(Some(&[ |
| 942 | + ("ip", &ValueRef::str("0.0.0.0")), |
| 943 | + ("mask", &ValueRef::int(0)), |
| 944 | + ])), |
| 945 | + ), |
| 946 | + ( |
| 947 | + ValueRef::str("::/0"), |
| 948 | + ValueRef::dict(Some(&[ |
| 949 | + ("ip", &ValueRef::str("::")), |
| 950 | + ("mask", &ValueRef::int(0)), |
| 951 | + ])), |
| 952 | + ), |
| 953 | + ( |
| 954 | + ValueRef::str("10.0.0.0/8"), |
| 955 | + ValueRef::dict(Some(&[ |
| 956 | + ("ip", &ValueRef::str("10.0.0.0")), |
| 957 | + ("mask", &ValueRef::int(8)), |
| 958 | + ])), |
| 959 | + ), |
| 960 | + ( |
| 961 | + ValueRef::str("2001:db8::/56"), |
| 962 | + ValueRef::dict(Some(&[ |
| 963 | + ("ip", &ValueRef::str("2001:db8::")), |
| 964 | + ("mask", &ValueRef::int(56)), |
| 965 | + ])), |
| 966 | + ), |
| 967 | + ( |
| 968 | + ValueRef::str("10.1.2.3/32"), |
| 969 | + ValueRef::dict(Some(&[ |
| 970 | + ("ip", &ValueRef::str("10.1.2.3")), |
| 971 | + ("mask", &ValueRef::int(32)), |
| 972 | + ])), |
| 973 | + ), |
| 974 | + ( |
| 975 | + ValueRef::str("2001:db8:1:2:3:4:5:7/128"), |
| 976 | + ValueRef::dict(Some(&[ |
| 977 | + ("ip", &ValueRef::str("2001:db8:1:2:3:4:5:7")), |
| 978 | + ("mask", &ValueRef::int(128)), |
| 979 | + ])), |
| 980 | + ), |
| 981 | + ( |
| 982 | + ValueRef::str("10.1.2.3"), |
| 983 | + ValueRef::dict(Some(&[ |
| 984 | + ("ip", &ValueRef::str("10.1.2.3")), |
| 985 | + ("mask", &ValueRef::int(32)), |
| 986 | + ])), |
| 987 | + ), |
| 988 | + ( |
| 989 | + ValueRef::str("2001:db8:1:2:3:4:5:7"), |
| 990 | + ValueRef::dict(Some(&[ |
| 991 | + ("ip", &ValueRef::str("2001:db8:1:2:3:4:5:7")), |
| 992 | + ("mask", &ValueRef::int(128)), |
| 993 | + ])), |
| 994 | + ), |
| 995 | + (ValueRef::str("10.0.0/8"), ValueRef::dict(None)), |
| 996 | + (ValueRef::str("10.0.0.0/33"), ValueRef::dict(None)), |
| 997 | + ( |
| 998 | + ValueRef::str("2001:db8:1:2:3:4:5:7/129"), |
| 999 | + ValueRef::dict(None), |
| 1000 | + ), |
| 1001 | + (ValueRef::str("0.0.0.0/256"), ValueRef::dict(None)), |
| 1002 | + (ValueRef::str("::/256"), ValueRef::dict(None)), |
| 1003 | + (ValueRef::str("10.0.0.0/8/8"), ValueRef::dict(None)), |
| 1004 | + (ValueRef::str("2001:db8::/56/56"), ValueRef::dict(None)), |
| 1005 | + (ValueRef::str("0.0.0.0/-1"), ValueRef::dict(None)), |
| 1006 | + (ValueRef::str("::/-1"), ValueRef::dict(None)), |
| 1007 | + (ValueRef::str("10.128.0.0/8"), ValueRef::dict(None)), |
| 1008 | + (ValueRef::str("2001:db8::/16"), ValueRef::dict(None)), |
| 1009 | + (ValueRef::str("10.1.2.3/31"), ValueRef::dict(None)), |
| 1010 | + ( |
| 1011 | + ValueRef::str("2001:db8:1:2:3:4:5:7/127"), |
| 1012 | + ValueRef::dict(None), |
| 1013 | + ), |
| 1014 | + ]; |
| 1015 | + let mut ctx = Context::default(); |
| 1016 | + for (cidr, expected) in cases.iter() { |
| 1017 | + unsafe { |
| 1018 | + let actual = &*kclvm_net_parse_CIDR( |
| 1019 | + &mut ctx, |
| 1020 | + &ValueRef::list(Some(&[&cidr])), |
| 1021 | + &ValueRef::dict(None), |
| 1022 | + ); |
| 1023 | + assert_eq!(expected, actual, "{} positional", cidr); |
| 1024 | + } |
| 1025 | + unsafe { |
| 1026 | + let actual = &*kclvm_net_parse_CIDR( |
| 1027 | + &mut ctx, |
| 1028 | + &ValueRef::list(None), |
| 1029 | + &ValueRef::dict(Some(&[("cidr", cidr)])), |
| 1030 | + ); |
| 1031 | + assert_eq!(expected, actual, "{} named", cidr); |
| 1032 | + } |
| 1033 | + } |
| 1034 | + } |
| 1035 | + |
| 1036 | + #[test] |
| 1037 | + #[allow(non_snake_case)] |
| 1038 | + fn test_parse_CIDR_invalid() { |
| 1039 | + let prev_hook = std::panic::take_hook(); |
| 1040 | + // Disable print panic info in stderr. |
| 1041 | + std::panic::set_hook(Box::new(|_| {})); |
| 1042 | + assert_panic( |
| 1043 | + "parse_CIDR() missing 1 required positional argument: 'cidr'", |
| 1044 | + || { |
| 1045 | + let mut ctx = Context::new(); |
| 1046 | + let args = ValueRef::list(None).into_raw(&mut ctx); |
| 1047 | + let kwargs = ValueRef::dict(None).into_raw(&mut ctx); |
| 1048 | + kclvm_net_parse_CIDR(ctx.into_raw(), args, kwargs); |
| 1049 | + }, |
| 1050 | + ); |
| 1051 | + std::panic::set_hook(prev_hook); |
| 1052 | + } |
937 | 1053 | }
|
0 commit comments