| Crates.io | haitaka-usi |
| lib.rs | haitaka-usi |
| version | 0.1.0 |
| created_at | 2025-05-04 17:05:19.868265+00 |
| updated_at | 2025-05-04 17:05:19.868265+00 |
| description | Universal Shogi Interface (USI) library |
| homepage | https://github.com/tofutofu/haitaka-usi |
| repository | https://github.com/tofutofu/haitaka-usi |
| max_upload_size | |
| id | 1659805 |
| size | 102,555 |
Haitaka-usi is a Universal Shogi Interface (USI) protocol parser and serializer.
The USI protocol is a simple, 7-bit-ascii-text-based protocol for Shogi clients and engines to communicate with each other. The protocol is based on the UCI (Universal Chess Interface) protocol with modifications to support Shogi.
The parser code in this repo uses a PEG/PEST grammar to define the protocol syntax. The grammar file, usi.pest, was originally inspired by the uci.pest file of Vampirc UCI, which was a great help in getting up to speed with PEST. But apart from making the required modifications to support Shogi, I also made some other pretty significant changes. In particular, I unified the top-level entry points (the start rule) which should make it easier to use and verify the grammar. I also clearly separated GUI messages from Engine messages, and I made a few other, smaller modifications to conform more closely to the spec. See comments in the usi.pest file for details.
This library implements serialization and deserialization for both the client (GUI) and server (engine) side. This makes it possible to use as a bridge between a server (Shogi engine frontend) and a client (GUI backend). It differs in this regard from the usi-rs crate which is an alternative implementation and an excellent GUI client, but which only supports deserialization of GUI commands and parsing of Engine commands.
Add haitaka-usi to your Cargo.toml:
[dependencies]
haitaka-usi = "0.1.0" # or use the latest version on crates.io
use haitaka_types::*;
use haitaka_usi::*;
// parse a multi-line sequence of messages
let input = "\
id name haitaka-shogi
id author tofutofu
option name Style type combo default Normal var Solid var Normal var Wild
option name USI_Hash type spin default 256
option name USI_Ponder type check default false
usiok
";
for msg in EngineMessageStream::new(input) {
println!("{msg:?}");
println!("{msg}");
}
// parse one line
let input = "bestmove 2g2f ponder 8c8d\n";
let bestmove = Move::BoardMove { from: Square::G2, to: Square::F2, promotion: false };
let ponder = Some(Move::BoardMove { from: Square::C8, to: Square::D8, promotion: false });
let msg = EngineMessage::parse(input).unwrap();
assert_eq!(
msg,
EngineMessage::BestMove(BestMoveParams::BestMove { bestmove, ponder })
);
// parse one line, skipping junk tokens
let input = "yo taka usiok\n";
let msg = EngineMessage::parse_first_valid(input).unwrap();
assert_eq!(msg, EngineMessage::UsiOk);
// parse a gui message multi-line input string
let input = "\
usinewgame
position startpos moves 7g7f 3c3d
go btime 300000 wtime 300000 byoyomi 10000
";
for msg in GuiMessageStream::new(input) {
println!("{msg:?}");
println!("{msg}");
}
// parse one line
let input = "usinewgame\n";
let msg = GuiMessage::parse(input).unwrap();
assert_eq!(msg, GuiMessage::UsiNewGame);
use haitaka_types::*;
use haitaka_usi::*;
let params = EngineParams::new().btime(300000).wtime(300000).byoyomi(10000);
let msg = GuiMessage::Go(params);
assert_eq!(format!("{msg}\n"), "go btime 300000 wtime 300000 byoyomi 10000\n");
let bestmove = Move::BoardMove { from: Square::G2, to: Square::F2, promotion: false };
let ponder = Some(Move::BoardMove { from: Square::C8, to: Square::D8, promotion: false });
let msg = EngineMessage::BestMove(BestMoveParams::BestMove { bestmove, ponder });
assert_eq!(format!("{msg}\n"), "bestmove 2g2f ponder 8c8d\n");
More examples can be found in the unit tests.
The API docs will be available at docs.rs/haitaka-usi.
The main limitation is that the current library does not support a real streaming protocol. All parser functions
require a complete input string. GuiMessageStream and EngineMessageStream can convert a given input string
into a sequence of message objects, but also require the input to be fully given.
usi
usinewgame
isready
debug
setoption
register
ponderhit
position
go
stop
quit
gameover
id
usiok
copyprotection
registration
option
readyok
bestmove
info
Contributions are very welcome! Please open an issue or submit a pull request on GitHub. Also, feel free to contact me on the Discord Shogi Harbour channel (@tofutofu).
haitaka-usi is licensed under the MIT license.