Overview of mug-protobuf
mastermug-protobuf module provides extra utilities for working with Protocol Buffers (protobuf). It is designed to extend standard protobuf capabilities within the Mug ecosystem.repository·master·Indexed 19 days ago
https://github.com/google/mugA lightweight Java 8+ library for string processing and stream utilities with zero dependencies. It includes dot-parse, a fluent parser combinator API for replacing regular expressions and defining recursive grammars, and dot-cel, a parser for the CEL AST that utilizes Java 21 pattern matching and sealed interfaces. The library also provides a secure, immutable email address parser in the com.google.common.labs.email package.
mug-protobuf module provides extra utilities for working with Protocol Buffers (protobuf). It is designed to extend standard protobuf capabilities within the Mug ecosystem.SafeSql is a compile-time checked SQL template library for Java designed to prevent accidental SQL injection while allowing developers to write direct, readable SQL. It uses a {placeholder} syntax to define parameters within a SQL string. These placeholders are automatically handled via JDBC PreparedStatement when executing queries, ensuring that parameter values are safely isolated from the SQL command structure.
// Construct a SafeSql with a template and two placeholder values {id} and {name}.
SafeSql sql = SafeSql.of(
"select id, name, age from users where id = {id} OR name LIKE '%{name}%'",
userId, userName);
// convenience method to map `ResultSet` to a list of records or Java beans.
List<User> users = sql.query(dataSource, User.class);The mu.util package provides two complementary libraries for structured string processing in Java:
StringFormat: Used for static, compile-time safe template formatting and parsing. It uses named placeholders (e.g., {id}) instead of positional specifiers.Substring: Used for dynamic, runtime composable substring extraction and splitting. It provides a chainable API for slicing strings safely using Optional-based returns.Use StringFormat when you have a known structure to parse or format, and Substring when you need to extract ranges or split strings based on dynamic delimiters.
The com.google.common.labs.email package provides a modern, declarative, and secure email address parser and domain model. It is built using compact parser combinators from dot-parse and is designed as a lightweight, thread-safe, and secure alternative to javax.mail.InternetAddress or Apache EmailValidator.
Key characteristics include:
EmailAddress is an immutable record, making it inherently thread-safe.Mug's string processing utilities are designed for safety and clarity:
StringFormat: Provides structured templates with named placeholders.Substring: Provides precise dynamic range selection.mug-guava artifact provides a set of utility classes designed to work seamlessly with both Mug and Guava. It includes tools for safe SQL query building, enhanced collection collectors, string case manipulation, generic binary searching, and improved factory methods for immutable collections.SafeSql is a library for writing injection-safe SQL templates in Java without using a DSL or XML. You should use SafeSql if you require:
name parameter where an ssn is expected) through type-safe parameter handling.The dot-cel parser is benchmarked against Google's official ANTLR-based Java CEL parser (cel-java using dev.cel:cel). Both parsers are functionally compatible as they construct identical ASTs (com.google.api.expr.v1alpha1.ParsedExpr) including source position metadata such as positions, macro_calls, and line_offsets.
In performance testing, dot-cel consistently demonstrates higher throughput (lower microseconds per operation) across various expression types, including deep field selections, comprehensions, and batch parsing.
| Benchmark Scenario / Expression | cel-java (ANTLR parser) | dot-cel (dot-parse Parser) | Speedup |
| :--- | :---: | :---: | :---: |
| **`deepFieldMessageSelection`** | 3.299 μs | 1.226 μs | **2.69x** |
| **`smokeTest`** | 2.712 μs | 1.020 μs | **2.66x** |
| **`anyFieldMessageSelection`** | 2.481 μs | 1.072 μs | **2.31x** |
| **`simpleMessageContext`** | 4.335 μs | 1.871 μs | **2.32x** |
| **`mapComprehension`** | 4.570 μs | 2.039 μs | **2.24x** |
| **`cppSuite`** | 368.501 μs | 167.147 μs | **2.20x** |
| **`listComprehension`** | 4.337 μs | 2.012 μs | **2.16x** |
| **`chainedOrs`** | 8.299 μs | 3.917 μs | **2.12x** |
| **`chainedAnds`** | 7.881 μs | 3.795 μs | **2.08x** |
| **`messageCreation`** | 14.000 μs | 7.345 μs | **1.91x** |
| **`longList`** | 793.293 μs | 477.317 μs | **1.66x** |Walker is a stream-based traversal utility designed for on-demand discovery of trees and graph structures, such as web link graphs or dependency DAGs. Unlike Guava's Traverser which returns an Iterable, Walker returns a Java Stream, allowing you to leverage standard stream operations like .filter(), .limit(), and .map() during traversal.
| Feature | Guava Traverser | Mug Walker |
|---|---|---|
| Return value | Iterable | Stream |
| Pre-order traversal | preOrderTraversal(...) | preOrderFrom(...) |
| Post-order traversal | postOrderTraversal(...) | postOrderFrom(...) |
| Breadth-first traversal | breadthFirst(...) | breadthFirstFrom(...) |
| Binary tree in-order | ❌ | inBinaryTree(...).inOrderFrom(...) |
| Strongly connected components | ❌ | stronglyConnectedComponentsFrom(...) |
| Cycle detection | ❌ | detectCycleFrom(...) |
| Topological order | ❌ | topologicalOrderFrom(...) |
| Shortest path (weighted) | ❌ | ShortestPath.shortestPathsFrom(...) |
A BiStream is a specialized API designed for fluently streaming through Map or Multimap entries. While Java 8's Stream is powerful, it becomes verbose when performing operations specifically on Map entries (like transforming keys or filtering values). BiStream provides a more readable and concise alternative for these common Map-centric patterns, reducing boilerplate code required for transformations and flattening.
// Standard Java 8 boilerplate for transforming and filtering Map keys
map.entrySet().stream()
.map(e -> Map.entry(transform(e.getKey()), e.getValue()))
.filter(e -> isGood(e.getKey()))
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
// Equivalent, more readable BiStream code
BiStream.from(map)
.mapKeys(this::transform)
.filterKeys(this::isGood)
.toMap();mug-errorprone plugin provides compile-time checks for the com.google.mu.util.StringFormat class (in Mug) and the com.google.mu.safesql.SafeSql class. It ensures that string templates used for parsing and formatting are used safely by catching potential errors during compilation rather than at runtime.Dot Parse disallows direct left recursion to prevent StackOverflowError. If you attempt to define a parser that calls itself at the start of its own definition, an IllegalStateException will be thrown at parse definition time.
For legitimate left-associative grammars (like binary operators or postfix operators), you should use the OperatorTable class instead of manual recursion. OperatorTable allows you to define these declaratively using precedence levels, which is cleaner than manually nesting sub-rules.
If you only have a single left-associative postfix operator, you can use the .withPostfixes() method on a parser.
// Using OperatorTable for left-associative postfix operators (e.g., field references like foo.bar)
Parser<Expr> expr = new OperatorTable<Expr>()
.postfix(string(".").then(identifier), FieldRef::new, 10)
.build(identifier.map(IdentifierRef::new));
// Using withPostfixes for a single postfix operator
Parser<Expr> expr = identifier.map(IdentifierRef::new)
.withPostfixes(string(".").then(identifier), FieldRef::new);