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

import go.Seq;

public final class S implements Seq.Proxy, I {
    static { Vars.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    S(Seq.Ref ref) { this.ref = ref; }
    
    public S() { this.ref = __New(); }
    
    private static native Seq.Ref __New();
    
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S)) {
            return false;
        }
        S that = (S)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("S").append("{");
        return b.append("}").toString();
    }
}

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

import go.Seq;

public interface I {
    
}

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

import go.Seq;

public abstract class Vars {
    static {
        Seq.touch(); // for loading the native library
        _init();
    }
    
    private Vars() {} // uninstantiable
    
    // touch is called from other bound packages to initialize this package
    public static void touch() {}
    
    private static native void _init();
    
    private static final class proxyI implements Seq.Proxy, I {
        private final Seq.Ref ref;
        
        @Override public final int incRefnum() {
              int refnum = ref.refnum;
              Seq.incGoRef(refnum);
              return refnum;
        }
        
        proxyI(Seq.Ref ref) { this.ref = ref; }
        
    }
    
    
    public static native void setABool(boolean v);
    public static native boolean getABool();
    
    public static native void setAFloat(double v);
    public static native double getAFloat();
    
    public static native void setAFloat32(float v);
    public static native float getAFloat32();
    
    public static native void setAFloat64(double v);
    public static native double getAFloat64();
    
    public static native void setAString(String v);
    public static native String getAString();
    
    public static native void setAStructPtr(S v);
    public static native S getAStructPtr();
    
    public static native void setAnInt(long v);
    public static native long getAnInt();
    
    public static native void setAnInt16(short v);
    public static native short getAnInt16();
    
    public static native void setAnInt32(int v);
    public static native int getAnInt32();
    
    public static native void setAnInt64(long v);
    public static native long getAnInt64();
    
    public static native void setAnInt8(byte v);
    public static native byte getAnInt8();
    
    public static native void setAnInterface(I v);
    public static native I getAnInterface();
    
}
