Add documentation for generated RFC utilities

This commit is contained in:
moznion
2021-01-03 15:03:00 +09:00
parent b395f51fdd
commit eaa171ec48
28 changed files with 1903 additions and 31 deletions

View File

@@ -135,7 +135,7 @@ fn main() {
let mut attribute_name_to_rfc_name: HashMap<String, String> = HashMap::new();
for dict_file_path in dict_file_paths {
let (radius_attributes, radius_attribute_to_values_map) =
let ((radius_attributes, radius_attribute_to_values_map), dict_file_lines) =
parse_dict_file(dict_file_path).unwrap();
let value_defined_attributes_set = radius_attribute_to_values_map
@@ -145,7 +145,7 @@ fn main() {
let rfc_name = dict_file_path.extension().unwrap().to_str().unwrap();
let mut w = BufWriter::new(File::create(out_dir.join(format!("{}.rs", rfc_name))).unwrap());
generate_header(&mut w, &rfc_names);
generate_header(&mut w, &rfc_names, rfc_name, dict_file_lines);
generate_attributes_code(&mut w, &radius_attributes, &value_defined_attributes_set);
generate_values_code(
&mut w,
@@ -160,20 +160,39 @@ fn main() {
}
}
fn generate_header(w: &mut BufWriter<File>, rfc_names: &[String]) {
let code = b"// Code generated by machine generator; DO NOT EDIT.
fn generate_header(
w: &mut BufWriter<File>,
rfc_names: &[String],
rfc_name: &str,
dict_file_lines: io::Lines<io::BufReader<File>>,
) {
let code = format!(
"// Code generated by machine generator; DO NOT EDIT.
use std::net::{Ipv4Addr, Ipv6Addr};
//! Utility for {rfc_name} packet.
//!
//! This module handles the packet according to the following definition:
//! ```text
//! {dict_file_contents}
//! ```
use chrono::{DateTime, Utc};
use std::net::{{Ipv4Addr, Ipv6Addr}};
use crate::core::avp::{AVP, AVPType, AVPError};
use chrono::{{DateTime, Utc}};
use crate::core::avp::{{AVP, AVPType, AVPError}};
use crate::core::packet::Packet;
use crate::core::tag::Tag;
";
",
rfc_name = rfc_name,
dict_file_contents = dict_file_lines
.map(|line| format!("//! {}", line.unwrap()))
.collect::<Vec<_>>()
.join("\n"),
);
w.write_all(code).unwrap();
w.write_all(code.as_bytes()).unwrap();
for rfc_name in rfc_names {
w.write_all(format!("use crate::core::{};\n", rfc_name).as_bytes())
@@ -331,7 +350,7 @@ fn generate_attribute_code(
RadiusAttributeValueType::Integer => {
match value_defined_attributes_set.contains(&attr_name) {
true => match attr.has_tag {
true => generate_value_tagged_defined_integer_attribute_code(
true => generate_tagged_value_defined_integer_attribute_code(
w,
&method_identifier,
&type_identifier,
@@ -373,6 +392,7 @@ fn generate_common_attribute_code(
let code = format!(
"
pub const {type_identifier}: AVPType = {type_value};
/// Delete all of `{method_identifier}` values from a packet.
pub fn delete_{method_identifier}(packet: &mut Packet) {{
packet.delete({type_identifier});
}}
@@ -390,12 +410,17 @@ fn generate_string_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &str) {{
"/// Add `{method_identifier}` string value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &str) {{
packet.add(AVP::from_string({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` string value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<String, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_string())
}}
/// Lookup all of the `{method_identifier}` string value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<String>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -416,12 +441,17 @@ fn generate_tagged_string_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: &str) {{
"/// Add `{method_identifier}` tagged string value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: &str) {{
packet.add(AVP::from_tagged_string({type_identifier}, tag, value));
}}
/// Lookup a `{method_identifier}` tagged string value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<(String, Option<Tag>), AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_tagged_string())
}}
/// Lookup all of the `{method_identifier}` tagged string value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<(String, Option<Tag>)>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -442,13 +472,18 @@ fn generate_user_password_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
"/// Add `{method_identifier}` user-password value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
packet.add(AVP::from_user_password({type_identifier}, value, packet.get_secret(), packet.get_authenticator())?);
Ok(())
}}
/// Lookup a `{method_identifier}` user-password value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<Vec<u8>, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_user_password(packet.get_secret(), packet.get_authenticator()))
}}
/// Lookup all of the `{method_identifier}` user-password value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<Vec<u8>>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -469,13 +504,18 @@ fn generate_tunnel_password_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: &[u8]) -> Result<(), AVPError> {{
"/// Add `{method_identifier}` tunnel-password value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: &[u8]) -> Result<(), AVPError> {{
packet.add(AVP::from_tunnel_password({type_identifier}, tag, value, packet.get_secret(), packet.get_authenticator())?);
Ok(())
}}
/// Lookup a `{method_identifier}` tunnel-password value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<(Vec<u8>, Tag), AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_tunnel_password(packet.get_secret(), packet.get_authenticator()))
}}
/// Lookup all of the `{method_identifier}` tunnel-password value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<(Vec<u8>, Tag)>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -496,12 +536,17 @@ fn generate_octets_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) {{
"/// Add `{method_identifier}` octets value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) {{
packet.add(AVP::from_bytes({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` octets value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Vec<u8>> {{
packet.lookup({type_identifier}).map(|v| v.encode_bytes())
}}
/// Lookup all of the `{method_identifier}` octets value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Vec<Vec<u8>> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -554,16 +599,21 @@ fn generate_fixed_length_octets_attribute_code(
fixed_octets_length: usize,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
"/// Add `{method_identifier}` fixed-length octets value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
if value.len() != {fixed_octets_length} {{
return Err(AVPError::InvalidAttributeLengthError(\"{fixed_octets_length} bytes\".to_owned(), value.len()));
}}
packet.add(AVP::from_bytes({type_identifier}, value));
Ok(())
}}
/// Lookup a `{method_identifier}` fixed-length octets value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Vec<u8>> {{
packet.lookup({type_identifier}).map(|v| v.encode_bytes())
}}
/// Lookup all of the `{method_identifier}` fixed-length octets value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Vec<Vec<u8>> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -585,12 +635,17 @@ fn generate_ipaddr_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv4Addr) {{
"/// Add `{method_identifier}` ipaddr value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv4Addr) {{
packet.add(AVP::from_ipv4({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` ipaddr value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_ipv4())
}}
/// Lookup all of the `{method_identifier}` ipaddr value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -611,13 +666,18 @@ fn generate_ipv4_prefix_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
"/// Add `{method_identifier}` ipv4 prefix value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
packet.add(AVP::from_ipv4_prefix({type_identifier}, value)?);
Ok(())
}}
/// Lookup a `{method_identifier}` ipv4 prefix value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<Vec<u8>, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_ipv4_prefix())
}}
/// Lookup all of the `{method_identifier}` ipv4 prefix value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<Vec<u8>>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -638,12 +698,17 @@ fn generate_ipv6addr_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv6Addr) {{
"/// Add `{method_identifier}` ipv6addr value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &Ipv6Addr) {{
packet.add(AVP::from_ipv6({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` ipv6addr value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<Ipv6Addr, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_ipv6())
}}
/// Lookup all of the `{method_identifier}` ipv6addr value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<Ipv6Addr>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -664,13 +729,18 @@ fn generate_ipv6_prefix_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
"/// Add `{method_identifier}` ipv6 prefix value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
packet.add(AVP::from_ipv6_prefix({type_identifier}, value)?);
Ok(())
}}
/// Lookup a `{method_identifier}` ipv6 prefix value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<Vec<u8>, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_ipv6_prefix())
}}
/// Lookup all of the `{method_identifier}` ipv6 prefix value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<Vec<u8>>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -691,12 +761,17 @@ fn generate_date_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &DateTime<Utc>) {{
"/// Add `{method_identifier}` date value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: &DateTime<Utc>) {{
packet.add(AVP::from_date({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` date value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<DateTime<Utc>, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_date())
}}
/// Lookup all of the `{method_identifier}` date value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<DateTime<Utc>>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -717,12 +792,17 @@ fn generate_integer_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: u32) {{
"/// Add `{method_identifier}` integer value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: u32) {{
packet.add(AVP::from_u32({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` integer value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<u32, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_u32())
}}
/// Lookup all of the `{method_identifier}` integer value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<u32>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -743,12 +823,17 @@ fn generate_tagged_integer_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: u32) {{
"/// Add `{method_identifier}` tagged integer value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: u32) {{
packet.add(AVP::from_tagged_u32({type_identifier}, tag, value));
}}
/// Lookup a `{method_identifier}` tagged integer value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<(u32, Tag), AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_tagged_u32())
}}
/// Lookup all of the `{method_identifier}` tagged integer value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<(u32, Tag)>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -770,12 +855,17 @@ fn generate_value_defined_integer_attribute_code(
value_type: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: {value_type}) {{
"/// Add `{method_identifier}` value-defined integer value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: {value_type}) {{
packet.add(AVP::from_u32({type_identifier}, value as u32));
}}
/// Lookup a `{method_identifier}` value-defined integer value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<{value_type}, AVPError>> {{
packet.lookup({type_identifier}).map(|v| Ok(v.encode_u32()? as {value_type}))
}}
/// Lookup all of the `{method_identifier}` value-defined integer value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<{value_type}>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -791,22 +881,27 @@ pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<{value_type
w.write_all(code.as_bytes()).unwrap();
}
fn generate_value_tagged_defined_integer_attribute_code(
fn generate_tagged_value_defined_integer_attribute_code(
w: &mut BufWriter<File>,
method_identifier: &str,
type_identifier: &str,
value_type: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: {value_type}) {{
"/// Add `{method_identifier}` tagged value-defined integer value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, tag: Option<&Tag>, value: {value_type}) {{
packet.add(AVP::from_tagged_u32({type_identifier}, tag, value as u32));
}}
/// Lookup a `{method_identifier}` tagged value-defined integer value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<({value_type}, Tag), AVPError>> {{
packet.lookup({type_identifier}).map(|v| {{
let (v, t) = v.encode_tagged_u32()?;
Ok((v as {value_type}, t))
}})
}}
/// Lookup all of the `{method_identifier}` tagged value-defined integer value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<({value_type}, Tag)>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -829,12 +924,17 @@ fn generate_short_attribute_code(
type_identifier: &str,
) {
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: u16) {{
"/// Add `{method_identifier}` short integer value to a packet.
pub fn add_{method_identifier}(packet: &mut Packet, value: u16) {{
packet.add(AVP::from_u16({type_identifier}, value));
}}
/// Lookup a `{method_identifier}` short integer value from a packet.
///
/// It returns the first looked up value. If there is no associated value with `{method_identifier}`, it returns `None`.
pub fn lookup_{method_identifier}(packet: &Packet) -> Option<Result<u16, AVPError>> {{
packet.lookup({type_identifier}).map(|v| v.encode_u16())
}}
/// Lookup all of the `{method_identifier}` short integer value from a packet.
pub fn lookup_all_{method_identifier}(packet: &Packet) -> Result<Vec<u16>, AVPError> {{
let mut vec = Vec::new();
for avp in packet.lookup_all({type_identifier}) {{
@@ -855,7 +955,9 @@ fn generate_vsa_attribute_code() {
type DictParsed = (Vec<RadiusAttribute>, BTreeMap<String, Vec<RadiusValue>>);
fn parse_dict_file(dict_file_path: &Path) -> Result<DictParsed, String> {
fn parse_dict_file(
dict_file_path: &Path,
) -> Result<(DictParsed, io::Lines<io::BufReader<File>>), String> {
let line_filter_re = Regex::new(r"^(?:#.*|)$").unwrap();
let tabs_re = Regex::new(r"\t+").unwrap();
let trailing_comment_re = Regex::new(r"\s*?#.+?$").unwrap();
@@ -937,8 +1039,6 @@ fn parse_dict_file(dict_file_path: &Path) -> Result<DictParsed, String> {
}
};
// TODO
radius_attributes.push(RadiusAttribute {
name: items[1].to_string(),
typ: items[2].parse().unwrap(),
@@ -972,5 +1072,8 @@ fn parse_dict_file(dict_file_path: &Path) -> Result<DictParsed, String> {
}
}
Ok((radius_attributes, radius_attribute_to_values))
Ok((
(radius_attributes, radius_attribute_to_values),
read_lines(dict_file_path).unwrap(),
))
}