I'm not sure this blog post makes the right comparison. Based on my admittedly limited experience, OCaml modules seem more comparable to Java classes than packages. They're both bundles of functions and data, except the module contains data types instead of being the data type itself. Classes have basically all the features of strong modules like separate compilation, signatures (interfaces), functors (generics), namespacing, access control. These examples of OCaml modules are all things that would be implemented as a class in Java.
From this perspective, rather than Java lacking strong modules, it actually has them in the form of classes. It's OCaml which lacks (or doesn't need) an additional package system on top of its modules.
Do you care about modeling the cells? If not, you could represent each row with just a number. When X plays, add 1 to all the rows that include the position they played, and when O plays, subtract 1. If any row reaches +3 or -3, that player wins.
As for rotation/reflection invariance, that seems more like a math problem than a Rust problem.