Java: added compiled metadata generation
This commit is contained in:
@@ -32,4 +32,4 @@ pub use phonenumberutil::{
|
|||||||
};
|
};
|
||||||
pub use proto_gen::phonemetadata;
|
pub use proto_gen::phonemetadata;
|
||||||
pub use proto_gen::phonenumber;
|
pub use proto_gen::phonenumber;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
|
* Copyright (C) 2025 Vladislav Kashin (modified)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
pub const METADATA: [u8; 201802] = [
|
pub const METADATA: [u8; 201802] = [
|
||||||
0x0A, 0xE9, 0x01, 0x0A, 0x1D, 0x12, 0x17, 0x28, 0x3F, 0x3A, 0x5B, 0x30, 0x31,
|
0x0A, 0xE9, 0x01, 0x0A, 0x1D, 0x12, 0x17, 0x28, 0x3F, 0x3A, 0x5B, 0x30, 0x31,
|
||||||
@@ -15525,4 +15541,3 @@ pub const METADATA: [u8; 201802] = [
|
|||||||
0xFF, 0x01, 0xE2, 0x01, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0x01, 0xE2, 0x01, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0x01
|
0xFF, 0xFF, 0x01
|
||||||
];
|
];
|
||||||
|
|
||||||
3
src/phonenumberutil/generated/mod.rs
Normal file
3
src/phonenumberutil/generated/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod metadata;
|
||||||
|
pub mod test_metadata;
|
||||||
|
|
||||||
@@ -1,5 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
|
* Copyright (C) 2025 Vladislav Kashin (modified)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
pub const METADATA: [u8; 13260] = [
|
pub const TEST_METADATA: [u8; 13260] = [
|
||||||
0x0A, 0xAD, 0x01, 0x0A, 0x09, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x36, 0x7D, 0x48,
|
0x0A, 0xAD, 0x01, 0x0A, 0x09, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x36, 0x7D, 0x48,
|
||||||
0x06, 0x12, 0x0F, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x36, 0x7D, 0x32, 0x06, 0x31,
|
0x06, 0x12, 0x0F, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x36, 0x7D, 0x32, 0x06, 0x31,
|
||||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x1A, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0x32, 0x33, 0x34, 0x35, 0x36, 0x1A, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
@@ -1020,4 +1036,4 @@ pub const METADATA: [u8; 13260] = [
|
|||||||
0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xCA, 0x01,
|
0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xCA, 0x01,
|
||||||
0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xE2,
|
0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xE2,
|
||||||
0x01, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01
|
0x01, 0x0B, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01
|
||||||
];
|
];
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
mod helper_constants;
|
mod helper_constants;
|
||||||
mod metadata;
|
|
||||||
|
|
||||||
pub(super) use helper_constants::{*};
|
pub(super) use helper_constants::{*};
|
||||||
pub(super) use metadata::METADATA;
|
|
||||||
|
|||||||
@@ -4,18 +4,17 @@ use protobuf::Message;
|
|||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
interfaces::MatcherApi,
|
interfaces::MatcherApi, phonenumberutil::generated::metadata::METADATA, proto_gen::{
|
||||||
proto_gen::{
|
|
||||||
phonemetadata::{PhoneMetadata, PhoneMetadataCollection, PhoneNumberDesc},
|
phonemetadata::{PhoneMetadata, PhoneMetadataCollection, PhoneNumberDesc},
|
||||||
phonenumber::PhoneNumber,
|
phonenumber::PhoneNumber,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
PhoneNumberFormat, PhoneNumberType, ValidNumberLenType,
|
PhoneNumberFormat, PhoneNumberType, ValidNumberLenType,
|
||||||
errors::ValidationResultErr,
|
errors::ValidationResultErr,
|
||||||
helper_constants::{
|
helper_constants::{
|
||||||
METADATA, OPTIONAL_EXT_SUFFIX, PLUS_SIGN, POSSIBLE_CHARS_AFTER_EXT_LABEL,
|
OPTIONAL_EXT_SUFFIX, PLUS_SIGN, POSSIBLE_CHARS_AFTER_EXT_LABEL,
|
||||||
POSSIBLE_SEPARATORS_BETWEEN_NUMBER_AND_EXT_LABEL, RFC3966_EXTN_PREFIX, RFC3966_PREFIX,
|
POSSIBLE_SEPARATORS_BETWEEN_NUMBER_AND_EXT_LABEL, RFC3966_EXTN_PREFIX, RFC3966_PREFIX,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub mod phonenumberutil;
|
|||||||
mod phone_number_regexps_and_mappings;
|
mod phone_number_regexps_and_mappings;
|
||||||
pub(self) mod helper_types;
|
pub(self) mod helper_types;
|
||||||
pub(self) mod comparisons;
|
pub(self) mod comparisons;
|
||||||
|
pub(crate) mod generated;
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
mod tests;
|
mod tests;
|
||||||
mod test_metadata;
|
|
||||||
@@ -10,13 +10,13 @@ use protobuf::Message;
|
|||||||
|
|
||||||
use crate::{errors::ParseError, phonemetadata::PhoneMetadataCollection, phonenumber::PhoneNumber, PhoneNumberUtil};
|
use crate::{errors::ParseError, phonemetadata::PhoneMetadataCollection, phonenumber::PhoneNumber, PhoneNumberUtil};
|
||||||
|
|
||||||
use super::test_metadata::METADATA;
|
use crate::phonenumberutil::generated::test_metadata::TEST_METADATA;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This setup function simulates getting the PhoneNumberUtil instance for each test.
|
// This setup function simulates getting the PhoneNumberUtil instance for each test.
|
||||||
fn get_phone_util() -> PhoneNumberUtil {
|
fn get_phone_util() -> PhoneNumberUtil {
|
||||||
let metadata = PhoneMetadataCollection::parse_from_bytes(&METADATA)
|
let metadata = PhoneMetadataCollection::parse_from_bytes(&TEST_METADATA)
|
||||||
.expect("Metadata should be valid");
|
.expect("Metadata should be valid");
|
||||||
// In a real scenario, this would likely return a singleton instance.
|
// In a real scenario, this would likely return a singleton instance.
|
||||||
return PhoneNumberUtil::new_for_metadata(metadata);
|
return PhoneNumberUtil::new_for_metadata(metadata);
|
||||||
|
|||||||
@@ -1 +1,11 @@
|
|||||||
## This directory contains script for autogeneration of metadata in rust
|
## This directory contains script for autogeneration of metadata in rust
|
||||||
|
|
||||||
|
To build from source cd /tools/java and
|
||||||
|
```
|
||||||
|
mvn install
|
||||||
|
```
|
||||||
|
|
||||||
|
Example command on build generator
|
||||||
|
```
|
||||||
|
java -jar tools\java\rust-build\target\rust-build-1.0-SNAPSHOT-jar-with-dependencies.jar BuildMetadataRustFromXml resources\PhoneNumberMetadata.xml ./test.rs metadata --const-name=test
|
||||||
|
```
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 The Libphonenumber Authors
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
|
* Copyright (C) %d Vladislav Kashin (modified)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,18 +25,16 @@ import java.util.Formatter;
|
|||||||
* Class containing the Apache copyright notice used by code generators.
|
* Class containing the Apache copyright notice used by code generators.
|
||||||
*
|
*
|
||||||
* @author Philippe Liard
|
* @author Philippe Liard
|
||||||
|
* @author Kashin Vladislav (modified for Rust code generation)
|
||||||
*/
|
*/
|
||||||
public class CopyrightNotice {
|
public class CopyrightNotice {
|
||||||
|
|
||||||
private static final String TEXT_OPENING =
|
private static final String TEXT_OPENING =
|
||||||
"/*\n";
|
"/*\n";
|
||||||
|
|
||||||
private static final String TEXT_OPENING_FOR_JAVASCRIPT =
|
|
||||||
"/**\n" +
|
|
||||||
" * @license\n";
|
|
||||||
|
|
||||||
private static final String TEXT =
|
private static final String TEXT =
|
||||||
" * Copyright (C) %d The Libphonenumber Authors\n" +
|
" * Copyright (C) %d The Libphonenumber Authors\n" +
|
||||||
|
" * Copyright (C) %d Vladislav Kashin (modified)\n" +
|
||||||
" *\n" +
|
" *\n" +
|
||||||
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
|
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
|
||||||
" * you may not use this file except in compliance with the License.\n" +
|
" * you may not use this file except in compliance with the License.\n" +
|
||||||
@@ -50,17 +49,9 @@ public class CopyrightNotice {
|
|||||||
" * limitations under the License.\n" +
|
" * limitations under the License.\n" +
|
||||||
" */\n\n";
|
" */\n\n";
|
||||||
|
|
||||||
static final void writeTo(Writer writer, int year) throws IOException {
|
static final void writeTo(Writer writer, int year, int yearSecondAuthor) throws IOException {
|
||||||
writeTo(writer, year, false);
|
writer.write(TEXT_OPENING);
|
||||||
}
|
|
||||||
|
|
||||||
static final void writeTo(Writer writer, int year, boolean isJavascript) throws IOException {
|
|
||||||
if (isJavascript) {
|
|
||||||
writer.write(TEXT_OPENING_FOR_JAVASCRIPT);
|
|
||||||
} else {
|
|
||||||
writer.write(TEXT_OPENING);
|
|
||||||
}
|
|
||||||
Formatter formatter = new Formatter(writer);
|
Formatter formatter = new Formatter(writer);
|
||||||
formatter.format(TEXT, year);
|
formatter.format(TEXT, year, yearSecondAuthor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,13 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.google.i18n.phonenumbers.tools</groupId>
|
<groupId>com.google.i18n.phonenumbers.tools</groupId>
|
||||||
<artifactId>cpp-build</artifactId>
|
<artifactId>rust-build</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<name>Libphonenumber C++ build tools</name>
|
<name>Libphonenumber Rust build tools</name>
|
||||||
<description>
|
<description>
|
||||||
C++ build tools that download dependencies under base/ from the Chromium source repository, and
|
Rust build tools that download dependencies under base/ from the Chromium source repository, and
|
||||||
generate the C++ metadata code needed to build the libphonenumber library.
|
generate the Rust metadata code needed to build the libphonenumber library.
|
||||||
|
It depends on libphonenumber original Java library.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -115,8 +116,6 @@
|
|||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- Build a JAR with its dependencies (protocol buffers and common library). This JAR
|
|
||||||
contains the C++ build tools invoked by CMake during the libphonenumber C++ build. -->
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 The Libphonenumber Authors
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
*
|
* Copyright (C) 2025 The Kashin Vladislav (modified)
|
||||||
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
|
|
||||||
package com.google.i18n.phonenumbers;
|
package com.google.i18n.phonenumbers;
|
||||||
|
|
||||||
import com.google.i18n.phonenumbers.CppMetadataGenerator.Type;
|
import com.google.i18n.phonenumbers.RustMetadataGenerator.Type;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -26,19 +27,22 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class generates the C++ code representation of the provided XML metadata file. It lets us
|
* This class generates the Rust code representation of the provided XML metadata file. It lets us
|
||||||
* embed metadata directly in a native binary. We link the object resulting from the compilation of
|
* embed metadata directly in a native binary. We link the object resulting from the compilation of
|
||||||
* the code emitted by this class with the C++ phonenumber library.
|
* the code emitted by this class with the Rust rlibphonenumber library.
|
||||||
*
|
*
|
||||||
* @author Philippe Liard
|
* @author Philippe Liard
|
||||||
* @author David Beaumont
|
* @author David Beaumont
|
||||||
|
*
|
||||||
|
* @author Kashin Vladislav (modified for Rust code generation)
|
||||||
*/
|
*/
|
||||||
public class BuildMetadataCppFromXml extends Command {
|
public class BuildMetadataRustFromXml extends Command {
|
||||||
|
|
||||||
/** An enum encapsulating the variations of metadata that we can produce. */
|
/** An enum encapsulating the variations of metadata that we can produce. */
|
||||||
public enum Variant {
|
public enum Variant {
|
||||||
@@ -93,22 +97,38 @@ public class BuildMetadataCppFromXml extends Command {
|
|||||||
static final class Options {
|
static final class Options {
|
||||||
private static final Pattern BASENAME_PATTERN =
|
private static final Pattern BASENAME_PATTERN =
|
||||||
Pattern.compile("(?:(test|lite)_)?([a-z_]+)");
|
Pattern.compile("(?:(test|lite)_)?([a-z_]+)");
|
||||||
|
private static final Pattern CONSTANT_NAME_PATTERN =
|
||||||
public static Options parse(String commandName, String[] args) {
|
Pattern.compile("--const-name[ =]([a-zA-Z_]+)");
|
||||||
if (args.length == 4) {
|
private static final String DEFAULT_METADATA_CONSTANT_NAME = "METADATA";
|
||||||
String inputXmlFilePath = args[1];
|
public static Options parse(String commandName, String[] argsArray) {
|
||||||
String outputDirPath = args[2];
|
ArrayList args = new ArrayList(Arrays.asList(argsArray));
|
||||||
Matcher basenameMatcher = BASENAME_PATTERN.matcher(args[3]);
|
String constantName = DEFAULT_METADATA_CONSTANT_NAME;
|
||||||
|
if (args.size() == 5) {
|
||||||
|
for (int i = 0; i < args.size(); i++) {
|
||||||
|
String arg = args.get(i).toString();
|
||||||
|
Matcher matcher = CONSTANT_NAME_PATTERN.matcher(arg.toString());
|
||||||
|
if (matcher.matches()) {
|
||||||
|
constantName = matcher.group(1);
|
||||||
|
args.remove(arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args.size() == 4) {
|
||||||
|
String inputXmlFilePath = args.get(1).toString();
|
||||||
|
String outputDirPath = args.get(2).toString();
|
||||||
|
Matcher basenameMatcher = BASENAME_PATTERN.matcher(args.get(3).toString());
|
||||||
if (basenameMatcher.matches()) {
|
if (basenameMatcher.matches()) {
|
||||||
Variant variant = Variant.parse(basenameMatcher.group(1));
|
Variant variant = Variant.parse(basenameMatcher.group(1));
|
||||||
Type type = Type.parse(basenameMatcher.group(2));
|
Type type = Type.parse(basenameMatcher.group(2));
|
||||||
if (type != null && variant != null) {
|
if (type != null && variant != null) {
|
||||||
return new Options(inputXmlFilePath, outputDirPath, type, variant);
|
return new Options(inputXmlFilePath, outputDirPath, type, variant, constantName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"Usage: %s <inputXmlFile> <outputDir> ( <type> | test_<type> | lite_<type> )\n" +
|
"Usage: %s <inputXmlFile> <outputDir> <output ( <type> | test_<type> | lite_<type> ) " +
|
||||||
|
"[--const-name <nameOfMetadataConstant>] \n" +
|
||||||
" where <type> is one of: %s",
|
" where <type> is one of: %s",
|
||||||
commandName, Arrays.asList(Type.values())));
|
commandName, Arrays.asList(Type.values())));
|
||||||
}
|
}
|
||||||
@@ -119,12 +139,14 @@ public class BuildMetadataCppFromXml extends Command {
|
|||||||
private final String outputDirPath;
|
private final String outputDirPath;
|
||||||
private final Type type;
|
private final Type type;
|
||||||
private final Variant variant;
|
private final Variant variant;
|
||||||
|
private final String constantName;
|
||||||
|
|
||||||
private Options(String inputXmlFilePath, String outputDirPath, Type type, Variant variant) {
|
private Options(String inputXmlFilePath, String outputDirPath, Type type, Variant variant, String constantName) {
|
||||||
this.inputXmlFilePath = inputXmlFilePath;
|
this.inputXmlFilePath = inputXmlFilePath;
|
||||||
this.outputDirPath = outputDirPath;
|
this.outputDirPath = outputDirPath;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.variant = variant;
|
this.variant = variant;
|
||||||
|
this.constantName = constantName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInputFilePath() {
|
public String getInputFilePath() {
|
||||||
@@ -142,17 +164,21 @@ public class BuildMetadataCppFromXml extends Command {
|
|||||||
public Variant getVariant() {
|
public Variant getVariant() {
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getConstantName() {
|
||||||
|
return constantName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCommandName() {
|
public String getCommandName() {
|
||||||
return "BuildMetadataCppFromXml";
|
return "BuildMetadataRustFromXml";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates C++ header and source files to represent the metadata specified by this command's
|
* Generates Rust source file to represent the metadata specified by this command's
|
||||||
* arguments. The metadata XML file is read and converted to a byte array before being written
|
* arguments. The metadata XML file is read and converted to a byte array before being written
|
||||||
* into a C++ source file as a static data array.
|
* into a Rust source file as a static data array.
|
||||||
*
|
*
|
||||||
* @return true if the generation succeeded.
|
* @return true if the generation succeeded.
|
||||||
*/
|
*/
|
||||||
@@ -161,16 +187,14 @@ public class BuildMetadataCppFromXml extends Command {
|
|||||||
try {
|
try {
|
||||||
Options opt = Options.parse(getCommandName(), getArgs());
|
Options opt = Options.parse(getCommandName(), getArgs());
|
||||||
byte[] data = loadMetadataBytes(opt.getInputFilePath(), opt.getVariant() == Variant.LITE);
|
byte[] data = loadMetadataBytes(opt.getInputFilePath(), opt.getVariant() == Variant.LITE);
|
||||||
CppMetadataGenerator metadata = CppMetadataGenerator.create(opt.getType(), data);
|
RustMetadataGenerator metadata = RustMetadataGenerator.create(opt.getType(), data, opt.constantName);
|
||||||
|
|
||||||
// TODO: Consider adding checking for correctness of file paths and access.
|
// TODO: Consider adding checking for correctness of file paths and access.
|
||||||
OutputStream headerStream = null;
|
OutputStream headerStream = null;
|
||||||
OutputStream sourceStream = null;
|
OutputStream sourceStream = null;
|
||||||
try {
|
try {
|
||||||
File dir = new File(opt.getOutputDir());
|
File dir = new File(opt.getOutputDir());
|
||||||
headerStream = openHeaderStream(dir, opt.getType());
|
sourceStream = openSourceStream(dir);
|
||||||
sourceStream = openSourceStream(dir, opt.getType(), opt.getVariant());
|
|
||||||
metadata.outputHeaderFile(new OutputStreamWriter(headerStream, UTF_8));
|
|
||||||
metadata.outputSourceFile(new OutputStreamWriter(sourceStream, UTF_8));
|
metadata.outputSourceFile(new OutputStreamWriter(sourceStream, UTF_8));
|
||||||
} finally {
|
} finally {
|
||||||
FileUtils.closeFiles(headerStream, sourceStream);
|
FileUtils.closeFiles(headerStream, sourceStream);
|
||||||
@@ -206,13 +230,8 @@ public class BuildMetadataCppFromXml extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @VisibleForTesting
|
// @VisibleForTesting
|
||||||
OutputStream openHeaderStream(File dir, Type type) throws FileNotFoundException {
|
OutputStream openSourceStream(File file) throws FileNotFoundException {
|
||||||
return new FileOutputStream(new File(dir, type + ".h"));
|
return new FileOutputStream(file);
|
||||||
}
|
|
||||||
|
|
||||||
// @VisibleForTesting
|
|
||||||
OutputStream openSourceStream(File dir, Type type, Variant variant) throws FileNotFoundException {
|
|
||||||
return new FileOutputStream(new File(dir, variant.getBasename(type) + ".cc"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The charset in which our source and header files will be written. */
|
/** The charset in which our source and header files will be written. */
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 The Libphonenumber Authors
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
|
* Copyright (C) 2025 The Kashin Vladislav (modified)
|
||||||
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,12 +22,14 @@ package com.google.i18n.phonenumbers;
|
|||||||
* Entry point class for C++ build tools.
|
* Entry point class for C++ build tools.
|
||||||
*
|
*
|
||||||
* @author Philippe Liard
|
* @author Philippe Liard
|
||||||
|
*
|
||||||
|
* @author Kashin Vladislav (modified for Rust code generation)
|
||||||
*/
|
*/
|
||||||
public class EntryPoint {
|
public class EntryPoint {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
boolean status = new CommandDispatcher(args, new Command[] {
|
boolean status = new CommandDispatcher(args, new Command[] {
|
||||||
new BuildMetadataCppFromXml()
|
new BuildMetadataRustFromXml()
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
System.exit(status ? 0 : 1);
|
System.exit(status ? 0 : 1);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 The Libphonenumber Authors
|
* Copyright (C) 2012 The Libphonenumber Authors
|
||||||
|
* Copyright (C) 2025 The Kashin Vladislav (modified)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,8 +28,10 @@ import java.util.Locale;
|
|||||||
*
|
*
|
||||||
* @author David Beaumont
|
* @author David Beaumont
|
||||||
* @author Philippe Liard
|
* @author Philippe Liard
|
||||||
|
*
|
||||||
|
* @author Kashin Vladislav (modified for Rust code generation)
|
||||||
*/
|
*/
|
||||||
public final class CppMetadataGenerator {
|
public final class RustMetadataGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The metadata type represents the known types of metadata and includes additional information
|
* The metadata type represents the known types of metadata and includes additional information
|
||||||
@@ -37,18 +40,18 @@ public final class CppMetadataGenerator {
|
|||||||
*/
|
*/
|
||||||
public enum Type {
|
public enum Type {
|
||||||
/** The basic phone number metadata (expected to be written to metadata.[h/cc]). */
|
/** The basic phone number metadata (expected to be written to metadata.[h/cc]). */
|
||||||
METADATA("metadata", 2011),
|
METADATA(2011, 2025),
|
||||||
/** The alternate format metadata (expected to be written to alternate_format.[h/cc]). */
|
/** The alternate format metadata (expected to be written to alternate_format.[h/cc]). */
|
||||||
ALTERNATE_FORMAT("alternate_format", 2012),
|
ALTERNATE_FORMAT(2012, 2025),
|
||||||
/** Metadata for short numbers (expected to be written to short_metadata.[h/cc]). */
|
/** Metadata for short numbers (expected to be written to short_metadata.[h/cc]). */
|
||||||
SHORT_NUMBERS("short_metadata", 2013);
|
SHORT_NUMBERS(2013, 2025);
|
||||||
|
|
||||||
private final String typeName;
|
|
||||||
private final int copyrightYear;
|
private final int copyrightYear;
|
||||||
|
private final int copyrightSecondYear;
|
||||||
|
|
||||||
private Type(String typeName, int copyrightYear) {
|
private Type(int copyrightYear, int CopyrightSecondYear) {
|
||||||
this.typeName = typeName;
|
|
||||||
this.copyrightYear = copyrightYear;
|
this.copyrightYear = copyrightYear;
|
||||||
|
this.copyrightSecondYear = CopyrightSecondYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the year in which this metadata type was first introduced. */
|
/** Returns the year in which this metadata type was first introduced. */
|
||||||
@@ -56,12 +59,9 @@ public final class CppMetadataGenerator {
|
|||||||
return copyrightYear;
|
return copyrightYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Returns the year in which this metadata type was modified for RUST. */
|
||||||
* Returns the name of this type for use in C++ source/header files. Use this in preference to
|
public int getCopyrightSecondYear() {
|
||||||
* using {@link #name}.
|
return copyrightSecondYear;
|
||||||
*/
|
|
||||||
@Override public String toString() {
|
|
||||||
return typeName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,93 +88,39 @@ public final class CppMetadataGenerator {
|
|||||||
* retained by the newly created CppXmlMetadata instance, so the caller should treat the array as
|
* retained by the newly created CppXmlMetadata instance, so the caller should treat the array as
|
||||||
* immutable after making this call.
|
* immutable after making this call.
|
||||||
*/
|
*/
|
||||||
public static CppMetadataGenerator create(Type type, byte[] data) {
|
public static RustMetadataGenerator create(Type type, byte[] data, String constantName) {
|
||||||
return new CppMetadataGenerator(type, data);
|
return new RustMetadataGenerator(type, data, constantName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Type type;
|
private final Type type;
|
||||||
private final byte[] data;
|
private final byte[] data;
|
||||||
private final String guardName; // e.g. "I18N_PHONENUMBERS_<TYPE>_H_"
|
private final String constantName;
|
||||||
private final String headerInclude; // e.g. "phonenumbers/<type>.h"
|
|
||||||
|
|
||||||
private CppMetadataGenerator(Type type, byte[] data) {
|
private RustMetadataGenerator(Type type, byte[] data, String variableName) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.guardName = createGuardName(type);
|
this.constantName = variableName;
|
||||||
this.headerInclude = createHeaderInclude(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the header file for the C++ representation of the metadata to the given writer. Note
|
* Writes the source file for the Rust representation of the metadata - a static array
|
||||||
* that this method does not close the given writer.
|
|
||||||
*/
|
|
||||||
public void outputHeaderFile(Writer out) throws IOException {
|
|
||||||
PrintWriter pw = new PrintWriter(out);
|
|
||||||
CopyrightNotice.writeTo(pw, type.getCopyrightYear());
|
|
||||||
pw.println("#ifndef " + guardName);
|
|
||||||
pw.println("#define " + guardName);
|
|
||||||
pw.println();
|
|
||||||
emitNamespaceStart(pw);
|
|
||||||
pw.println();
|
|
||||||
pw.println("int " + type + "_size();");
|
|
||||||
pw.println("const void* " + type + "_get();");
|
|
||||||
pw.println();
|
|
||||||
emitNamespaceEnd(pw);
|
|
||||||
pw.println();
|
|
||||||
pw.println("#endif // " + guardName);
|
|
||||||
pw.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the source file for the C++ representation of the metadata, including a static array
|
|
||||||
* containing the data itself, to the given writer. Note that this method does not close the given
|
* containing the data itself, to the given writer. Note that this method does not close the given
|
||||||
* writer.
|
* writer.
|
||||||
*/
|
*/
|
||||||
public void outputSourceFile(Writer out) throws IOException {
|
public void outputSourceFile(Writer out) throws IOException {
|
||||||
// TODO: Consider outputting a load method to return the parsed proto directly.
|
// TODO: Consider outputting a load method to return the parsed proto directly.
|
||||||
|
String dataLength = String.valueOf(data.length);
|
||||||
|
|
||||||
|
|
||||||
PrintWriter pw = new PrintWriter(out);
|
PrintWriter pw = new PrintWriter(out);
|
||||||
CopyrightNotice.writeTo(pw, type.getCopyrightYear());
|
CopyrightNotice.writeTo(pw, type.getCopyrightYear(), type.getCopyrightSecondYear());
|
||||||
pw.println("#include \"" + headerInclude + "\"");
|
pw.println("pub const "+constantName+": [u8; "+dataLength+"] = [");
|
||||||
pw.println();
|
|
||||||
emitNamespaceStart(pw);
|
|
||||||
pw.println();
|
|
||||||
pw.println("namespace {");
|
|
||||||
pw.println("static const unsigned char data[] = {");
|
|
||||||
emitStaticArrayData(pw, data);
|
emitStaticArrayData(pw, data);
|
||||||
pw.println("};");
|
pw.println("];");
|
||||||
pw.println("} // namespace");
|
|
||||||
pw.println();
|
|
||||||
pw.println("int " + type + "_size() {");
|
|
||||||
pw.println(" return sizeof(data) / sizeof(data[0]);");
|
|
||||||
pw.println("}");
|
|
||||||
pw.println();
|
|
||||||
pw.println("const void* " + type + "_get() {");
|
|
||||||
pw.println(" return data;");
|
|
||||||
pw.println("}");
|
|
||||||
pw.println();
|
|
||||||
emitNamespaceEnd(pw);
|
|
||||||
pw.flush();
|
pw.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createGuardName(Type type) {
|
/** Emits the Rust code corresponding to the binary metadata as a static byte array. */
|
||||||
return String.format("I18N_PHONENUMBERS_%s_H_", type.toString().toUpperCase(Locale.ENGLISH));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createHeaderInclude(Type type) {
|
|
||||||
return String.format("phonenumbers/%s.h", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void emitNamespaceStart(PrintWriter pw) {
|
|
||||||
pw.println("namespace i18n {");
|
|
||||||
pw.println("namespace phonenumbers {");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void emitNamespaceEnd(PrintWriter pw) {
|
|
||||||
pw.println("} // namespace phonenumbers");
|
|
||||||
pw.println("} // namespace i18n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Emits the C++ code corresponding to the binary metadata as a static byte array. */
|
|
||||||
// @VisibleForTesting
|
// @VisibleForTesting
|
||||||
static void emitStaticArrayData(PrintWriter pw, byte[] data) {
|
static void emitStaticArrayData(PrintWriter pw, byte[] data) {
|
||||||
String separator = " ";
|
String separator = " ";
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 The Libphonenumber Authors
|
* Copyright (C) 2011 The Libphonenumber Authors
|
||||||
|
* Copyright (C) 2025 The Kashin Vladislav (modified)
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -21,9 +22,9 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import com.google.i18n.phonenumbers.BuildMetadataCppFromXml.Options;
|
import com.google.i18n.phonenumbers.BuildMetadataRustFromXml.Options;
|
||||||
import com.google.i18n.phonenumbers.BuildMetadataCppFromXml.Variant;
|
import com.google.i18n.phonenumbers.BuildMetadataRustFromXml.Variant;
|
||||||
import com.google.i18n.phonenumbers.CppMetadataGenerator.Type;
|
import com.google.i18n.phonenumbers.RustMetadataGenerator.Type;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ import java.nio.charset.Charset;
|
|||||||
* Tests the BuildMetadataCppFromXml implementation to make sure it parses command line options and
|
* Tests the BuildMetadataCppFromXml implementation to make sure it parses command line options and
|
||||||
* generates code correctly.
|
* generates code correctly.
|
||||||
*/
|
*/
|
||||||
public class BuildMetadataCppFromXmlTest {
|
public class BuildMetadataRustFromXmlTest {
|
||||||
|
|
||||||
// Various repeated test strings and data.
|
// Various repeated test strings and data.
|
||||||
private static final String IGNORED = "IGNORED";
|
private static final String IGNORED = "IGNORED";
|
||||||
@@ -44,7 +45,9 @@ public class BuildMetadataCppFromXmlTest {
|
|||||||
private static final String INPUT_PATH_XML = "input/path.xml";
|
private static final String INPUT_PATH_XML = "input/path.xml";
|
||||||
private static final byte[] TEST_DATA =
|
private static final byte[] TEST_DATA =
|
||||||
new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE };
|
new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE };
|
||||||
private static final String CPP_TEST_DATA = "0xCA, 0xFE, 0xBA, 0xBE";
|
private static final int TEST_DATA_LEN = TEST_DATA.length;
|
||||||
|
private static final String TEST_CONSTANT_NAME = "METADATA";
|
||||||
|
private static final String OUTPUT_DATA = "0xCA, 0xFE, 0xBA, 0xBE";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseVariant() {
|
public void parseVariant() {
|
||||||
@@ -60,7 +63,7 @@ public class BuildMetadataCppFromXmlTest {
|
|||||||
@Test
|
@Test
|
||||||
public void parseBadOptions() {
|
public void parseBadOptions() {
|
||||||
try {
|
try {
|
||||||
BuildMetadataCppFromXml.Options.parse("MyCommand", new String[] { IGNORED });
|
BuildMetadataRustFromXml.Options.parse("MyCommand", new String[] { IGNORED });
|
||||||
fail("Expected exception not thrown");
|
fail("Expected exception not thrown");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
assertTrue(e.getMessage().contains("MyCommand"));
|
assertTrue(e.getMessage().contains("MyCommand"));
|
||||||
@@ -69,93 +72,58 @@ public class BuildMetadataCppFromXmlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseGoodOptions() {
|
public void parseGoodOptions() {
|
||||||
Options opt = BuildMetadataCppFromXml.Options.parse("MyCommand",
|
Options opt = BuildMetadataRustFromXml.Options.parse("MyCommand",
|
||||||
new String[] { IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "test_alternate_format" });
|
new String[] { IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "test_alternate_format", "--const-name=" + TEST_CONSTANT_NAME });
|
||||||
assertEquals(Type.ALTERNATE_FORMAT, opt.getType());
|
assertEquals(Type.ALTERNATE_FORMAT, opt.getType());
|
||||||
assertEquals(Variant.TEST, opt.getVariant());
|
assertEquals(Variant.TEST, opt.getVariant());
|
||||||
assertEquals(INPUT_PATH_XML, opt.getInputFilePath());
|
assertEquals(INPUT_PATH_XML, opt.getInputFilePath());
|
||||||
assertEquals(OUTPUT_DIR, opt.getOutputDir());
|
assertEquals(OUTPUT_DIR, opt.getOutputDir());
|
||||||
|
assertEquals(TEST_CONSTANT_NAME, opt.getConstantName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateMetadata() {
|
public void generateMetadata() {
|
||||||
String[] args = new String[] {
|
String[] args = new String[] {
|
||||||
IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "metadata" };
|
IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "metadata", "--const-name " + TEST_CONSTANT_NAME };
|
||||||
// Most of the useful asserts are done in the mock class.
|
// Most of the useful asserts are done in the mock class.
|
||||||
MockedCommand command = new MockedCommand(
|
MockedCommand command = new MockedCommand(
|
||||||
INPUT_PATH_XML, false, OUTPUT_DIR, Type.METADATA, Variant.FULL);
|
INPUT_PATH_XML, false, OUTPUT_DIR, Type.METADATA, Variant.FULL, TEST_CONSTANT_NAME
|
||||||
|
);
|
||||||
command.setArgs(args);
|
command.setArgs(args);
|
||||||
command.start();
|
command.start();
|
||||||
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
|
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
|
||||||
String headerString = command.capturedHeaderFile();
|
|
||||||
assertTrue(headerString.contains("const void* metadata_get()"));
|
|
||||||
assertTrue(headerString.contains("int metadata_size()"));
|
|
||||||
String sourceString = command.capturedSourceFile();
|
String sourceString = command.capturedSourceFile();
|
||||||
assertTrue(sourceString.contains("const void* metadata_get()"));
|
assertTrue(sourceString.contains("pub const "+TEST_CONSTANT_NAME+": [u8; " + TEST_DATA_LEN + "] ="));
|
||||||
assertTrue(sourceString.contains("int metadata_size()"));
|
assertTrue(sourceString.contains(OUTPUT_DATA));
|
||||||
assertTrue(sourceString.contains(CPP_TEST_DATA));
|
assertTrue(sourceString.contains("];"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// no need test for metadata with other names since it's set with parameter
|
||||||
public void generateLiteMetadata() {
|
|
||||||
String[] args = new String[] {
|
|
||||||
IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "lite_metadata" };
|
|
||||||
// Most of the useful asserts are done in the mock class.
|
|
||||||
MockedCommand command = new MockedCommand(
|
|
||||||
INPUT_PATH_XML, true, OUTPUT_DIR, Type.METADATA, Variant.LITE);
|
|
||||||
command.setArgs(args);
|
|
||||||
command.start();
|
|
||||||
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
|
|
||||||
String headerString = command.capturedHeaderFile();
|
|
||||||
assertTrue(headerString.contains("const void* metadata_get()"));
|
|
||||||
assertTrue(headerString.contains("int metadata_size()"));
|
|
||||||
String sourceString = command.capturedSourceFile();
|
|
||||||
assertTrue(sourceString.contains("const void* metadata_get()"));
|
|
||||||
assertTrue(sourceString.contains("int metadata_size()"));
|
|
||||||
assertTrue(sourceString.contains(CPP_TEST_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void generateAlternateFormat() {
|
|
||||||
String[] args = new String[] {
|
|
||||||
IGNORED, INPUT_PATH_XML, OUTPUT_DIR, "alternate_format" };
|
|
||||||
// Most of the useful asserts are done in the mock class.
|
|
||||||
MockedCommand command = new MockedCommand(
|
|
||||||
INPUT_PATH_XML, false, OUTPUT_DIR, Type.ALTERNATE_FORMAT, Variant.FULL);
|
|
||||||
command.setArgs(args);
|
|
||||||
command.start();
|
|
||||||
// Sanity check the captured data (asserting implicitly that the mocked methods were called).
|
|
||||||
String headerString = command.capturedHeaderFile();
|
|
||||||
assertTrue(headerString.contains("const void* alternate_format_get()"));
|
|
||||||
assertTrue(headerString.contains("int alternate_format_size()"));
|
|
||||||
String sourceString = command.capturedSourceFile();
|
|
||||||
assertTrue(sourceString.contains("const void* alternate_format_get()"));
|
|
||||||
assertTrue(sourceString.contains("int alternate_format_size()"));
|
|
||||||
assertTrue(sourceString.contains(CPP_TEST_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manually mocked subclass of BuildMetadataCppFromXml which overrides all file related behavior
|
* Manually mocked subclass of BuildMetadataCppFromXml which overrides all file related behavior
|
||||||
* while asserting the validity of any parameters passed to the mocked methods. After starting
|
* while asserting the validity of any parameters passed to the mocked methods. After starting
|
||||||
* this command, the captured header and source file contents can be retrieved for testing.
|
* this command, the captured header and source file contents can be retrieved for testing.
|
||||||
*/
|
*/
|
||||||
static class MockedCommand extends BuildMetadataCppFromXml {
|
static class MockedCommand extends BuildMetadataRustFromXml {
|
||||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||||
private final String expectedInputFilePath;
|
private final String expectedInputFilePath;
|
||||||
private final boolean expectedLiteMetadata;
|
private final boolean expectedLiteMetadata;
|
||||||
private final String expectedOutputDirPath;
|
private final String expectedOutputDirPath;
|
||||||
private final Type expectedType;
|
private final Type expectedType;
|
||||||
private final Variant expectedVariant;
|
private final Variant expectedVariant;
|
||||||
private final ByteArrayOutputStream headerOut = new ByteArrayOutputStream();
|
private final String expectedConstantName;
|
||||||
private final ByteArrayOutputStream sourceOut = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream sourceOut = new ByteArrayOutputStream();
|
||||||
|
|
||||||
public MockedCommand(String expectedInputFilePath, boolean expectedLiteMetadata,
|
public MockedCommand(String expectedInputFilePath, boolean expectedLiteMetadata,
|
||||||
String expectedOutputDirPath, Type expectedType, Variant expectedVariant) {
|
String expectedOutputDirPath, Type expectedType, Variant expectedVariant,
|
||||||
|
String expectedConstantName) {
|
||||||
|
|
||||||
this.expectedInputFilePath = expectedInputFilePath;
|
this.expectedInputFilePath = expectedInputFilePath;
|
||||||
this.expectedLiteMetadata = expectedLiteMetadata;
|
this.expectedLiteMetadata = expectedLiteMetadata;
|
||||||
this.expectedOutputDirPath = expectedOutputDirPath;
|
this.expectedOutputDirPath = expectedOutputDirPath;
|
||||||
this.expectedType = expectedType;
|
this.expectedType = expectedType;
|
||||||
|
this.expectedConstantName = expectedConstantName;
|
||||||
this.expectedVariant = expectedVariant;
|
this.expectedVariant = expectedVariant;
|
||||||
}
|
}
|
||||||
@Override void writePhoneMetadataCollection(
|
@Override void writePhoneMetadataCollection(
|
||||||
@@ -164,20 +132,11 @@ public class BuildMetadataCppFromXmlTest {
|
|||||||
assertEquals(expectedLiteMetadata, liteMetadata);
|
assertEquals(expectedLiteMetadata, liteMetadata);
|
||||||
out.write(TEST_DATA, 0, TEST_DATA.length);
|
out.write(TEST_DATA, 0, TEST_DATA.length);
|
||||||
}
|
}
|
||||||
@Override OutputStream openHeaderStream(File dir, Type type) {
|
@Override OutputStream openSourceStream(File dir) {
|
||||||
assertEquals(expectedOutputDirPath, dir.getPath());
|
assertEquals(expectedOutputDirPath, dir.getPath());
|
||||||
assertEquals(expectedType, type);
|
|
||||||
return headerOut;
|
|
||||||
}
|
|
||||||
@Override OutputStream openSourceStream(File dir, Type type, Variant variant) {
|
|
||||||
assertEquals(expectedOutputDirPath, dir.getPath());
|
|
||||||
assertEquals(expectedType, type);
|
|
||||||
assertEquals(expectedVariant, variant);
|
|
||||||
return sourceOut;
|
return sourceOut;
|
||||||
}
|
}
|
||||||
String capturedHeaderFile() {
|
|
||||||
return new String(headerOut.toByteArray(), UTF_8);
|
|
||||||
}
|
|
||||||
String capturedSourceFile() {
|
String capturedSourceFile() {
|
||||||
return new String(sourceOut.toByteArray(), UTF_8);
|
return new String(sourceOut.toByteArray(), UTF_8);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 The Libphonenumber Authors
|
* Copyright (C) 2012 The Libphonenumber Authors
|
||||||
*
|
* Copyright (C) 2025 The Kashin Vladislav (modified)
|
||||||
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@@ -19,7 +20,7 @@ package com.google.i18n.phonenumbers;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import com.google.i18n.phonenumbers.CppMetadataGenerator.Type;
|
import com.google.i18n.phonenumbers.RustMetadataGenerator.Type;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -35,60 +36,42 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Tests that the CppXmlMetadata class emits the expected source and header files for metadata.
|
* Tests that the CppXmlMetadata class emits the expected source and header files for metadata.
|
||||||
*/
|
*/
|
||||||
public class CppMetadataGeneratorTest {
|
public class RustMetadataGeneratorTest {
|
||||||
|
|
||||||
@Test
|
// 13 bytes per line, so have 16 bytes to test > 1 line (general case).
|
||||||
public void emitStaticArrayData() {
|
// Use all hex digits in both nibbles to test hex formatting.
|
||||||
// 13 bytes per line, so have 16 bytes to test > 1 line (general case).
|
private static final byte[] TEST_DATA = new byte[] {
|
||||||
// Use all hex digits in both nibbles to test hex formatting.
|
|
||||||
byte[] data = new byte[] {
|
|
||||||
(byte) 0xF0, (byte) 0xE1, (byte) 0xD2, (byte) 0xC3,
|
(byte) 0xF0, (byte) 0xE1, (byte) 0xD2, (byte) 0xC3,
|
||||||
(byte) 0xB4, (byte) 0xA5, (byte) 0x96, (byte) 0x87,
|
(byte) 0xB4, (byte) 0xA5, (byte) 0x96, (byte) 0x87,
|
||||||
(byte) 0x78, (byte) 0x69, (byte) 0x5A, (byte) 0x4B,
|
(byte) 0x78, (byte) 0x69, (byte) 0x5A, (byte) 0x4B,
|
||||||
(byte) 0x3C, (byte) 0x2D, (byte) 0x1E, (byte) 0x0F,
|
(byte) 0x3C, (byte) 0x2D, (byte) 0x1E, (byte) 0x0F,
|
||||||
};
|
};
|
||||||
|
private static final int TEST_DATA_LEN = TEST_DATA.length;
|
||||||
StringWriter writer = new StringWriter();
|
private static final String TEST_CONSTANT_NAME = "METADATA";
|
||||||
CppMetadataGenerator.emitStaticArrayData(new PrintWriter(writer), data);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputHeaderFile() throws IOException {
|
public void emitStaticArrayData() {
|
||||||
byte[] data = new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE };
|
|
||||||
CppMetadataGenerator metadata = CppMetadataGenerator.create(Type.METADATA, data);
|
byte[] data = TEST_DATA;
|
||||||
|
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
metadata.outputHeaderFile(writer);
|
RustMetadataGenerator.emitStaticArrayData(new PrintWriter(writer), data);
|
||||||
Iterator<String> lines = toLines(writer.toString()).iterator();
|
|
||||||
// Sanity check that at least some of the expected lines are present.
|
|
||||||
assertTrue(consumeUntil(" * Copyright (C) 2011 The Libphonenumber Authors", lines));
|
|
||||||
assertTrue(consumeUntil("#ifndef I18N_PHONENUMBERS_METADATA_H_", lines));
|
|
||||||
assertTrue(consumeUntil("#define I18N_PHONENUMBERS_METADATA_H_", lines));
|
|
||||||
assertTrue(consumeUntil("namespace i18n {", lines));
|
|
||||||
assertTrue(consumeUntil("namespace phonenumbers {", lines));
|
|
||||||
assertTrue(consumeUntil("int metadata_size();", lines));
|
|
||||||
assertTrue(consumeUntil("const void* metadata_get();", lines));
|
|
||||||
assertTrue(consumeUntil("#endif // I18N_PHONENUMBERS_METADATA_H_", lines));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputSourceFile() throws IOException {
|
public void outputSourceFile() throws IOException {
|
||||||
byte[] data = new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE };
|
byte[] data = new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE };
|
||||||
CppMetadataGenerator metadata = CppMetadataGenerator.create(Type.ALTERNATE_FORMAT, data);
|
String testDataLen = String.valueOf(data.length);
|
||||||
|
RustMetadataGenerator metadata = RustMetadataGenerator.create(Type.ALTERNATE_FORMAT, data, TEST_CONSTANT_NAME);
|
||||||
|
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
metadata.outputSourceFile(writer);
|
metadata.outputSourceFile(writer);
|
||||||
Iterator<String> lines = toLines(writer.toString()).iterator();
|
Iterator<String> lines = toLines(writer.toString()).iterator();
|
||||||
// Sanity check that at least some of the expected lines are present.
|
// Sanity check that at least some of the expected lines are present.
|
||||||
assertTrue(consumeUntil(" * Copyright (C) 2012 The Libphonenumber Authors", lines));
|
assertTrue(consumeUntil("pub const "+TEST_CONSTANT_NAME+": [u8; "+testDataLen+"] = [", lines));
|
||||||
assertTrue(consumeUntil("namespace i18n {", lines));
|
|
||||||
assertTrue(consumeUntil("namespace phonenumbers {", lines));
|
|
||||||
assertTrue(consumeUntil("namespace {", lines));
|
|
||||||
assertTrue(consumeUntil("static const unsigned char data[] = {", lines));
|
|
||||||
assertTrue(consumeUntil(" 0xCA, 0xFE, 0xBA, 0xBE", lines));
|
assertTrue(consumeUntil(" 0xCA, 0xFE, 0xBA, 0xBE", lines));
|
||||||
assertTrue(consumeUntil("int alternate_format_size() {", lines));
|
assertTrue(consumeUntil("];", lines));
|
||||||
assertTrue(consumeUntil("const void* alternate_format_get() {", lines));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts a string containing newlines into a list of lines. */
|
/** Converts a string containing newlines into a list of lines. */
|
||||||
33
tools/scripts/generate_metadata.sh
Normal file
33
tools/scripts/generate_metadata.sh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
filedir="./$(dirname "$0")"
|
||||||
|
javadir="$filedir/../java"
|
||||||
|
project_home="$filedir/../.."
|
||||||
|
generated_dir="$project_home/src/phonenumberutil/generated"
|
||||||
|
echo $generated_dir
|
||||||
|
|
||||||
|
resources_dir="$project_home/resources"
|
||||||
|
rust_build_jar="$javadir/rust-build/target/rust-build-1.0-SNAPSHOT-jar-with-dependencies.jar"
|
||||||
|
|
||||||
|
# mvn -f "$javadir/pom.xml" install
|
||||||
|
mkdir -p "$generated_dir"
|
||||||
|
|
||||||
|
function generate {
|
||||||
|
java -jar "$rust_build_jar" \
|
||||||
|
BuildMetadataRustFromXml \
|
||||||
|
"$resources_dir/$1" \
|
||||||
|
"$generated_dir/$2.rs" \
|
||||||
|
"$3" \
|
||||||
|
"--const-name=$4"
|
||||||
|
}
|
||||||
|
|
||||||
|
# generate general metadata
|
||||||
|
generate "PhoneNumberMetadata.xml" "metadata" "metadata" "METADATA"
|
||||||
|
|
||||||
|
# generate short metadata
|
||||||
|
generate "PhoneNumberMetadataForTesting.xml" "test_metadata" "metadata" "TEST_METADATA"
|
||||||
|
|
||||||
|
echo "\
|
||||||
|
pub mod metadata;
|
||||||
|
pub mod test_metadata;
|
||||||
|
" > "$generated_dir/mod.rs"
|
||||||
Reference in New Issue
Block a user