// Java class go.structs.Structs is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package go.structs;

import go.Seq;

public abstract class Structs {
    private Structs() {} // uninstantiable
    
    public static S Identity(S s) {
        go.Seq _in = new go.Seq();
        go.Seq _out = new go.Seq();
        S _result;
        _in.writeRef(s.ref());
        Seq.send(DESCRIPTOR, CALL_Identity, _in, _out);
        _result = new S(_out.readRef());
        return _result;
    }
    
    public static S IdentityWithError(S s) throws Exception {
        go.Seq _in = new go.Seq();
        go.Seq _out = new go.Seq();
        S _result;
        _in.writeRef(s.ref());
        Seq.send(DESCRIPTOR, CALL_IdentityWithError, _in, _out);
        _result = new S(_out.readRef());
        String _err = _out.readString();
        if (_err != null && !_err.isEmpty()) {
            throw new Exception(_err);
        }
        return _result;
    }
    
    public static final class S implements go.Seq.Object {
        private static final String DESCRIPTOR = "go.structs.S";
        private static final int FIELD_X_GET = 0x00f;
        private static final int FIELD_X_SET = 0x01f;
        private static final int FIELD_Y_GET = 0x10f;
        private static final int FIELD_Y_SET = 0x11f;
        private static final int CALL_Identity = 0x00c;
        private static final int CALL_Sum = 0x10c;
        
        private go.Seq.Ref ref;
        
        private S(go.Seq.Ref ref) { this.ref = ref; }
        
        public go.Seq.Ref ref() { return ref; }
        
        public void call(int code, go.Seq in, go.Seq out) {
            throw new RuntimeException("internal error: cycle: cannot call concrete proxy");
        }
        
        public double getX() {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            Seq.send(DESCRIPTOR, FIELD_X_GET, in, out);
            return out.readFloat64();
        }
        
        public void setX(double v) {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            in.writeFloat64(v);
            Seq.send(DESCRIPTOR, FIELD_X_SET, in, out);
        }
        
        public double getY() {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            Seq.send(DESCRIPTOR, FIELD_Y_GET, in, out);
            return out.readFloat64();
        }
        
        public void setY(double v) {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            in.writeFloat64(v);
            Seq.send(DESCRIPTOR, FIELD_Y_SET, in, out);
        }
        
        public S Identity() throws Exception {
            go.Seq _in = new go.Seq();
            go.Seq _out = new go.Seq();
            S _result;
            _in.writeRef(ref);
            Seq.send(DESCRIPTOR, CALL_Identity, _in, _out);
            _result = new S(_out.readRef());
            String _err = _out.readString();
            if (_err != null && !_err.isEmpty()) {
                throw new Exception(_err);
            }
            return _result;
        }
        
        public double Sum() {
            go.Seq _in = new go.Seq();
            go.Seq _out = new go.Seq();
            double _result;
            _in.writeRef(ref);
            Seq.send(DESCRIPTOR, CALL_Sum, _in, _out);
            _result = _out.readFloat64();
            return _result;
        }
        
        @Override public boolean equals(Object o) {
            if (o == null || !(o instanceof S)) {
                return false;
            }
            S that = (S)o;
            double thisX = getX();
            double thatX = that.getX();
            if (thisX != thatX) {
                return false;
            }
            double thisY = getY();
            double thatY = that.getY();
            if (thisY != thatY) {
                return false;
            }
            return true;
        }
        
        @Override public int hashCode() {
            return java.util.Arrays.hashCode(new Object[] {getX(), getY()});
        }
        
        @Override public String toString() {
            StringBuilder b = new StringBuilder();
            b.append("S").append("{");
            b.append("X:").append(getX()).append(",");
            b.append("Y:").append(getY()).append(",");
            return b.append("}").toString();
        }
        
    }
    
    private static final int CALL_Identity = 1;
    private static final int CALL_IdentityWithError = 2;
    private static final String DESCRIPTOR = "structs";
}
