diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/AbortCommand.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/AbortCommand.java index 88dc462ed..cecb53ae5 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/AbortCommand.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/AbortCommand.java @@ -67,10 +67,10 @@ public boolean isCommand() { } @Override - public void response(ZscriptExpression resp) { + public void onResponse(ZscriptExpression resp) { } @Override - public void notExecuted() { + public void onNotExecuted() { } } diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/BlankCommand.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/BlankCommand.java index 2e60c7de5..0470da190 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/BlankCommand.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/BlankCommand.java @@ -65,10 +65,10 @@ public byte[] compile(boolean includeParens) { } @Override - public void response(ZscriptExpression resp) { + public void onResponse(ZscriptExpression resp) { } @Override - public void notExecuted() { + public void onNotExecuted() { } } diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/CommandSeqElement.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/CommandSeqElement.java index fb8fb8809..e2b396a17 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/CommandSeqElement.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/CommandSeqElement.java @@ -1,5 +1,8 @@ package net.zscript.javaclient.commandbuilder; +/** + * An element of a Command Sequence under construction, representing a node in the Syntax Tree of a sequence during building. + */ public abstract class CommandSeqElement { protected CommandSeqElement parent = null; diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/FailureCommand.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/FailureCommand.java index 76e2d3091..b79f79545 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/FailureCommand.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/FailureCommand.java @@ -67,10 +67,10 @@ public byte[] compile(boolean includeParens) { } @Override - public void response(ZscriptExpression resp) { + public void onResponse(ZscriptExpression resp) { } @Override - public void notExecuted() { + public void onNotExecuted() { } } diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/OrSeqElement.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/OrSeqElement.java index 7a80f6eb5..2aaf28e3d 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/OrSeqElement.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/OrSeqElement.java @@ -2,6 +2,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UncheckedIOException; public class OrSeqElement extends CommandSeqElement { final CommandSeqElement before; @@ -43,7 +44,7 @@ public byte[] compile(boolean includeParens) { out.write((byte) '|'); out.write(after.compile(false)); } catch (IOException e) { - throw new RuntimeException(e); + throw new UncheckedIOException(e); } if (includeParens) { out.write((byte) ')'); diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommand.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommand.java index 3af5ffb3d..a6b513ec9 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommand.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommand.java @@ -4,8 +4,12 @@ import java.util.List; import net.zscript.javareceiver.tokenizer.ZscriptExpression; +import net.zscript.model.components.Zchars; public abstract class ZscriptCommand extends CommandSeqElement { + /** + * Represents the next command from a given point in the Syntax Tree based on the AND/OR logic of a command sequence. + */ public static class ZscriptSequencePath { private final List markers; private final ZscriptCommand next; @@ -30,13 +34,18 @@ public ZscriptCommand getNext() { } } - public abstract void notExecuted(); + public abstract void onNotExecuted(); - public abstract void response(ZscriptExpression resp); + /** + * Performs a command's listener callbacks when given a command's response. + * + * @param resp + */ + public abstract void onResponse(ZscriptExpression resp); public static ZscriptSequencePath findFirstCommand(final CommandSeqElement start) { CommandSeqElement current = start; - CommandSeqElement prev = null; + CommandSeqElement prev; List markers = new ArrayList<>(); while (!current.isCommand()) { if (current.getClass() == AndSeqElement.class) { @@ -48,8 +57,9 @@ public static ZscriptSequencePath findFirstCommand(final CommandSeqElement start } else { throw new IllegalStateException("Unknown CommandSeqElement: " + current); } + if (current.getClass() == OrSeqElement.class && prev.getClass() == OrSeqElement.class) { - markers.add((byte) '('); + markers.add(Zchars.Z_OPENPAREN); } } return new ZscriptSequencePath(markers, (ZscriptCommand) current); @@ -64,7 +74,7 @@ public ZscriptSequencePath findNext() { if (current.getClass() == OrSeqElement.class) { OrSeqElement orAncestor = (OrSeqElement) current; if (prev == orAncestor.before) { - markers.add((byte) '|'); + markers.add(Zchars.Z_ORELSE); return new ZscriptSequencePath(markers, findFirstCommand(orAncestor.after)); } } else if (current.getClass() == AndSeqElement.class) { @@ -72,13 +82,14 @@ public ZscriptSequencePath findNext() { if (prev != andAncestor.getElements().get(andAncestor.getElements().size() - 1)) { CommandSeqElement next = andAncestor.getElements().get(andAncestor.getElements().indexOf(prev) + 1); if (prev.getClass() != OrSeqElement.class && next.getClass() != OrSeqElement.class) { - markers.add((byte) '&'); + markers.add(Zchars.Z_ANDTHEN); } return new ZscriptSequencePath(markers, findFirstCommand(next)); } } + if (current.getClass() == OrSeqElement.class && current.getParent() != null && current.getParent().getClass() != OrSeqElement.class) { - markers.add((byte) ')'); + markers.add(Zchars.Z_CLOSEPAREN); } prev = current; current = current.getParent(); @@ -95,12 +106,12 @@ public ZscriptSequencePath findFailPath() { if (current.getClass() == OrSeqElement.class) { OrSeqElement orAncestor = (OrSeqElement) current; if (prev == orAncestor.before) { - markers.add((byte) '|'); + markers.add(Zchars.Z_ORELSE); return new ZscriptSequencePath(markers, findFirstCommand(orAncestor.after)); } } if (current.getClass() == OrSeqElement.class && current.getParent() != null && current.getParent().getClass() != OrSeqElement.class) { - markers.add((byte) ')'); + markers.add(Zchars.Z_CLOSEPAREN); } prev = current; current = current.getParent(); @@ -119,13 +130,13 @@ public ZscriptSequencePath findSuccessPath() { if (prev != andAncestor.getElements().get(andAncestor.getElements().size() - 1)) { CommandSeqElement next = andAncestor.getElements().get(andAncestor.getElements().indexOf(prev) + 1); if (prev.getClass() != OrSeqElement.class && next.getClass() != OrSeqElement.class) { - markers.add((byte) '&'); + markers.add(Zchars.Z_ANDTHEN); } return new ZscriptSequencePath(markers, findFirstCommand(next)); } } if (current.getClass() == OrSeqElement.class && current.getParent() != null && current.getParent().getClass() != OrSeqElement.class) { - markers.add((byte) ')'); + markers.add(Zchars.Z_CLOSEPAREN); } prev = current; current = current.getParent(); diff --git a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommandBuilder.java b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommandBuilder.java index ba7a9de98..0599f7d38 100644 --- a/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommandBuilder.java +++ b/clients/java-client-lib/client-command-api/src/main/java/net/zscript/javaclient/commandbuilder/ZscriptCommandBuilder.java @@ -17,6 +17,11 @@ import net.zscript.javareceiver.tokenizer.ZscriptExpression; import net.zscript.model.components.Zchars; +/** + * The builder for creating a ZscriptBuiltCommand. + * + * @param the type of response this command would expect to receive + */ public abstract class ZscriptCommandBuilder { private static final int BIGFIELD_REQD_OFFSET = 26; @@ -25,6 +30,9 @@ public abstract class ZscriptCommandBuilder { private final Map fields = new HashMap<>(); private final BitSet requiredFields = new BitSet(); + /** + * A representation of a command, returned by calling {@link #build()} on the builder, ready for amalgamation into a command sequence. + */ public class ZscriptBuiltCommand extends ZscriptCommand { @Override @@ -66,7 +74,7 @@ public byte[] compile(boolean includeParens) { } @Override - public void response(ZscriptExpression resp) { + public void onResponse(ZscriptExpression resp) { T parsed = parseResponse(resp); for (ZscriptResponseListener listener : listeners) { listener.accept(parsed); @@ -74,7 +82,7 @@ public void response(ZscriptExpression resp) { } @Override - public void notExecuted() { + public void onNotExecuted() { for (ZscriptResponseListener listener : listeners) { listener.notExecuted(); } diff --git a/clients/java-client-lib/client-command-builders/src/test/java/net/zscript/model/modules/testing/test/JavaCommandBuilderResponseTest.java b/clients/java-client-lib/client-command-builders/src/test/java/net/zscript/model/modules/testing/test/JavaCommandBuilderResponseTest.java index fdbe30d88..faf1091f0 100644 --- a/clients/java-client-lib/client-command-builders/src/test/java/net/zscript/model/modules/testing/test/JavaCommandBuilderResponseTest.java +++ b/clients/java-client-lib/client-command-builders/src/test/java/net/zscript/model/modules/testing/test/JavaCommandBuilderResponseTest.java @@ -235,7 +235,7 @@ private void checkResponse(final String responseChar ZscriptCommand cmd = commandBuilder.addResponseListener(listener) .build(); - cmd.response(new ZscriptTokenExpression(tokenReader::iterator)); + cmd.onResponse(new ZscriptTokenExpression(tokenReader::iterator)); } } diff --git a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseQueue.java b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseQueue.java index 515f9a47e..7728bf8dc 100644 --- a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseQueue.java +++ b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseQueue.java @@ -2,6 +2,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; @@ -11,6 +12,7 @@ import net.zscript.javaclient.commandbuilder.CommandSeqElement; import net.zscript.javaclient.commandbuilder.ZscriptCommandBuilder; import net.zscript.javaclient.connection.ResponseParser.ResponseHeader; +import net.zscript.model.components.Zchars; public class CommandResponseQueue implements CommandResponseSystem { private static final int MAX_SENT = 10; @@ -19,12 +21,111 @@ public class CommandResponseQueue implements CommandResponseSystem { private final ZscriptConnection connection; + private final Deque sent = new ArrayDeque<>(); + private final Queue toSend = new ArrayDeque<>(); + + private int currentAutoEchoNumber = 0; + private boolean canPipeline = true; + private interface CommandEntry { byte[] compile(); boolean canBePipelined(); } + public CommandResponseQueue(ZscriptConnection connection) { + this.connection = connection; + connection.onReceive(resp -> { + ResponseHeader header = ResponseParser.parseResponseHeader(resp); + if (header.getAddr().length == 0) { + callback(resp, header.getEcho(), header.getType()); + } else { + addrSystem.response(header.getAddr(), resp); + } + }); + } + + @Override + public void send(final ZscriptAddress addr, final byte[] data) { + if (sent.size() < MAX_SENT && canPipeline) { + AddrCommandSeqElEntry el = new AddrCommandSeqElEntry(data, addr); + sent.add(el); + connection.send(el.compile()); + } else { + toSend.add(new AddrCommandSeqElEntry(data, addr)); + } + } + + @Override + public void send(final CommandSeqElement seq) { + if (sent.size() < MAX_SENT && canPipeline) { + CommandSeqElEntry el = new CommandSeqElEntry(seq, currentAutoEchoNumber); + sent.add(el); + connection.send(el.compile()); + } else { + toSend.add(new CommandSeqElEntry(seq, currentAutoEchoNumber)); + } + currentAutoEchoNumber++; + if (currentAutoEchoNumber >= 0x10000) { + currentAutoEchoNumber = 0; + } + } + + @Override + public void send(final byte[] zscript, final Consumer callback) { + if (sent.isEmpty()) { + ByteArrEntry el = new ByteArrEntry(callback, zscript); + sent.add(el); + connection.send(el.compile()); + canPipeline = false; + } else { + toSend.add(new ByteArrEntry(callback, zscript)); + } + } + + /** + * @param response + * @param echo + * @param respType + */ + private void callback(final byte[] response, int echo, int respType) { + if (respType != 0) { + // TODO: notifications + } else if (!canPipeline) { + ((ByteArrEntry) sent.poll()).callback(response); + canPipeline = true; + } else { + boolean found = false; + for (final Iterator iterator = sent.iterator(); iterator.hasNext(); ) { + CommandEntry entryPlain = iterator.next(); + if (entryPlain.getClass() == CommandSeqElEntry.class && ((CommandSeqElEntry) entryPlain).getEcho() == echo) { + ((CommandSeqElEntry) entryPlain).callback(response); + iterator.remove(); + found = true; + break; + } + } + if (!found) { + throw new IllegalStateException("Command Response system doesn't know this response"); + } + } + if (!toSend.isEmpty()) { + CommandEntry entry = toSend.peek(); + if (sent.isEmpty()) { + sent.add(entry); + canPipeline = entry.canBePipelined(); + toSend.poll(); + } else if (sent.size() < MAX_SENT && canPipeline && entry.canBePipelined()) { + sent.add(toSend.poll()); + } + } + } + + @Override + public ResponseAddressingSystem getResponseAddressingSystem() { + return new ResponseAddressingSystem(this); + } + private class CommandSeqElEntry implements CommandEntry { private final CommandSeqElement cmdSeq; private final int echo; @@ -37,7 +138,7 @@ public CommandSeqElEntry(final CommandSeqElement cmdSeq, final int echo) { @Override public byte[] compile() { // TODO: decide on how locking will work... - byte[] echoF = ZscriptCommandBuilder.formatField((byte) '_', echo); + byte[] echoF = ZscriptCommandBuilder.formatField(Zchars.Z_ECHO, echo); byte[] startData = cmdSeq.compile(false); ByteArrayOutputStream str = new ByteArrayOutputStream(startData.length + echoF.length + 1); @@ -46,7 +147,7 @@ public byte[] compile() { str.write(startData); str.write('\n'); } catch (IOException e) { - throw new RuntimeException(e); + throw new UncheckedIOException(e); } return str.toByteArray(); } @@ -120,104 +221,4 @@ public boolean canBePipelined() { return false; } } - - private final Deque sent = new ArrayDeque<>(); - private final Queue toSend = new ArrayDeque<>(); - - private int currentEcho = 0; - private boolean canPipeline = true; - - public CommandResponseQueue(ZscriptConnection connection) { - this.connection = connection; - connection.onReceive(resp -> { - ResponseHeader header = ResponseParser.parseResponseHeader(resp); - if (header.getAddr().length == 0) { - callback(resp, header.getEcho(), header.getType()); - } else { - addrSystem.response(header.getAddr(), resp); - } - }); - } - - @Override - public void send(final ZscriptAddress addr, final byte[] data) { - if (sent.size() < MAX_SENT && canPipeline) { - AddrCommandSeqElEntry el = new AddrCommandSeqElEntry(data, addr); - sent.add(el); - connection.send(el.compile()); - } else { - toSend.add(new AddrCommandSeqElEntry(data, addr)); - } - } - - @Override - public void send(final CommandSeqElement seq) { - if (sent.size() < MAX_SENT && canPipeline) { - CommandSeqElEntry el = new CommandSeqElEntry(seq, currentEcho); - sent.add(el); - connection.send(el.compile()); - } else { - toSend.add(new CommandSeqElEntry(seq, currentEcho)); - } - currentEcho++; - if (currentEcho >= 0x10000) { - currentEcho = 0; - } - } - - @Override - public void send(final byte[] zscript, final Consumer callback) { - if (sent.isEmpty()) { - ByteArrEntry el = new ByteArrEntry(callback, zscript); - sent.add(el); - connection.send(el.compile()); - canPipeline = false; - } else { - toSend.add(new ByteArrEntry(callback, zscript)); - } - } - - /** - * @param response - * @param echo - * @param respType - */ - private void callback(final byte[] response, int echo, int respType) { - if (respType != 0) { - // TODO: notifications - } else if (!canPipeline) { - ((ByteArrEntry) sent.poll()).callback(response); - canPipeline = true; - } else { - boolean found = false; - for (final Iterator iterator = sent.iterator(); iterator.hasNext(); ) { - CommandEntry entryPlain = iterator.next(); - if (entryPlain.getClass() == CommandSeqElEntry.class && ((CommandSeqElEntry) entryPlain).getEcho() == echo) { - ((CommandSeqElEntry) entryPlain).callback(response); - iterator.remove(); - found = true; - break; - } - } - if (!found) { - throw new IllegalStateException("Command Response system doesn't know this response"); - } - } - if (!toSend.isEmpty()) { - CommandEntry entry = toSend.peek(); - if (sent.isEmpty()) { - sent.add(entry); - canPipeline = entry.canBePipelined(); - toSend.poll(); - } else if (sent.size() < MAX_SENT && canPipeline && entry.canBePipelined()) { - sent.add(toSend.poll()); - } - } - } - - @Override - public ResponseAddressingSystem getResponseAddressingSystem() { - return new ResponseAddressingSystem(this); - } - } diff --git a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseSystem.java b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseSystem.java index 15fbdadb7..ce1ee37ae 100644 --- a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseSystem.java +++ b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/CommandResponseSystem.java @@ -4,6 +4,9 @@ import net.zscript.javaclient.commandbuilder.CommandSeqElement; +/** + * Defines an entity which can take a zscript message in low-level form (byte[]) or high level ( + */ public interface CommandResponseSystem { void send(CommandSeqElement seq); diff --git a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/ResponseParser.java b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/ResponseParser.java index 7e6671cb4..9bf427d62 100644 --- a/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/ResponseParser.java +++ b/clients/java-client-lib/client-connection/src/main/java/net/zscript/javaclient/connection/ResponseParser.java @@ -201,14 +201,14 @@ private static void matchMarkers(final CommandSeqElement command, final List dataIn = new ArrayDeque<>(); - private Consumer handler; + private final ExecutorService exec = Executors.newSingleThreadExecutor(); + private final Queue dataIn = new ArrayDeque<>(); + private Consumer handler; private class ProgressForever implements Runnable { private final Zscript zscript; @@ -45,8 +45,8 @@ public LocalZscriptConnection() { zscript.addModule(new ZscriptCoreModule()); zscript.addModule(new ZscriptOuterCoreModule()); - TokenRingBuffer rbuff = TokenRingBuffer.createBufferWithCapacity(100); - zscript.addChannel(new ZscriptChannel(rbuff, new OutputStreamOutStream<>(new ByteArrayOutputStream()) { + TokenRingBuffer ringBuffer = TokenRingBuffer.createBufferWithCapacity(100); + zscript.addChannel(new ZscriptChannel(ringBuffer, new OutputStreamOutStream<>(new ByteArrayOutputStream()) { @Override public void close() { @@ -54,10 +54,10 @@ public void close() { getOutputStream().reset(); } }) { - Tokenizer in = new Tokenizer(rbuff.getTokenWriter(), 2); + final Tokenizer in = new Tokenizer(ringBuffer.getTokenWriter(), 2); byte[] current = null; - int pos = 0; + int pos = 0; @Override public void moveAlong() { diff --git a/clients/java-client-lib/client-connection/src/test/java/net/zscript/javaclient/connection/Main2.java b/clients/java-client-lib/client-connection/src/test/java/net/zscript/javaclient/connection/Main2.java index 77639bfaa..c55ac15f4 100644 --- a/clients/java-client-lib/client-connection/src/test/java/net/zscript/javaclient/connection/Main2.java +++ b/clients/java-client-lib/client-connection/src/test/java/net/zscript/javaclient/connection/Main2.java @@ -21,11 +21,12 @@ public static void main(String[] args) { ZscriptAddress address = ZscriptAddress.from(0x50, 0x0, 0x1); ZscriptConnection addressConnection = zscriptOut.getResponseAddressingSystem().getAddressConnection(address); + CommandResponseSystem zscriptOutAddr = new CommandResponseQueue(addressConnection); - zscriptOutAddr.send(CoreModule.capabilities() - .versionType(PlatformFirmware) - .addResponseListener(r -> System.out.println(r.getIdent())) - .build()); + // zscriptOutAddr.send(CoreModule.capabilities() + // .versionType(PlatformFirmware) + // .addResponseListener(r -> System.out.println(r.getIdent())) + // .build()); } } diff --git a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/AbstractOutStream.java b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/AbstractOutStream.java index 53ab0e2e2..ea19c8931 100644 --- a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/AbstractOutStream.java +++ b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/AbstractOutStream.java @@ -56,14 +56,9 @@ private void writeEscaped(byte b) { } private void writeStringByte(byte b) { - switch (b) { - case '\n': - case '=': - case '"': - case '\0': + if (Zchars.mustStringEscape(b)) { writeEscaped(b); - break; - default: + } else { writeCharAsByte(b); } } diff --git a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/ZscriptChannel.java b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/ZscriptChannel.java index 8e155522b..6d344e37e 100644 --- a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/ZscriptChannel.java +++ b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/core/ZscriptChannel.java @@ -7,16 +7,25 @@ import net.zscript.javareceiver.semanticParser.SemanticParser; import net.zscript.javareceiver.tokenizer.TokenBuffer; +/** + * Abstract implementation of a Channel that integrates a parser and buffer, and a source of actions that execute the received commands. As an ActionSource, it provides executable + * Actions. Implementors must supply: + *
    + *
  • {@link #channelInfo(CommandContext)}
  • + *
  • {@link #channelSetup(CommandContext)}
  • + *
  • either: an independent background means to write to the Tokenizer, or a {@link #moveAlong()} implementation to keep feeding it synchronously.
  • + *
+ */ public abstract class ZscriptChannel implements ActionSource { protected final SemanticParser p; - protected final OutStream out; + protected final OutStream out; - public ZscriptChannel(final SemanticParser p, final OutStream out) { + protected ZscriptChannel(final SemanticParser p, final OutStream out) { this.p = p; this.out = out; } - public ZscriptChannel(final TokenBuffer buffer, final OutStream out) { + protected ZscriptChannel(final TokenBuffer buffer, final OutStream out) { this(new SemanticParser(buffer.getTokenReader(), new ExecutionActionFactory()), out); } @@ -34,6 +43,9 @@ public SemanticAction getAction() { return p.getAction(); } + /** + * If this Channel is synchronous and needs prodding, then this method should be overridden to feed bytes into the Tokenizer. + */ public void moveAlong() { } diff --git a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/semanticParser/SemanticAction.java b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/semanticParser/SemanticAction.java index 3afedc67d..7227927df 100644 --- a/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/semanticParser/SemanticAction.java +++ b/receivers/jvm/java-receiver-token/src/main/java/net/zscript/javareceiver/semanticParser/SemanticAction.java @@ -11,7 +11,7 @@ import net.zscript.model.components.ZscriptStatus; public class SemanticAction implements ZscriptAction { - enum ActionType { + public enum ActionType { INVALID, GO_AROUND, WAIT_FOR_TOKENS, diff --git a/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/demoRun/Main.java b/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/demoRun/Main.java index 209515a5f..1194bdaee 100644 --- a/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/demoRun/Main.java +++ b/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/demoRun/Main.java @@ -30,8 +30,8 @@ public static void main(String[] args) throws IOException { TokenRingBuffer rbuff = TokenRingBuffer.createBufferWithCapacity(100); OutStream out = new ZscriptPrintingOutStream(); zscript.addChannel(new ZscriptChannel(rbuff, out) { - Tokenizer in = new Tokenizer(rbuff.getTokenWriter(), 2); - private int i = 0; + final Tokenizer in = new Tokenizer(rbuff.getTokenWriter(), 2); + private int i = 0; @Override public void moveAlong() { diff --git a/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/fullRun/StringChannel.java b/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/fullRun/StringChannel.java index 6706e5b0c..1c10346dc 100644 --- a/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/fullRun/StringChannel.java +++ b/receivers/jvm/java-receiver-token/src/test/java/net/zscript/javareceiver/fullRun/StringChannel.java @@ -38,5 +38,4 @@ public void channelInfo(CommandContext ctx) { @Override public void channelSetup(CommandContext ctx) { } - }