Proper way to port something written in C++ to Rust?

I've got a couple projects I'm considering porting to Rust (primarily for the learning experience, though I may release them as crates). Both are open source, of course. One is written in C and the other is written in C++. The C one shouldn't be overly difficult to port; its the C++ one I'm concerned about.

The C++ one is called LabSound. Its a C++ implementation of, and extension to, the WebAudio specification. It uses some C idioms though that make things that I'm unsure of the analog of in Rust. Example: in src/core/OscillatorNode.cpp, it uses something like:

    if (m_detune->hasSampleAccurateValues())
    {
        // Get the sample-accurate detune values.
        float* detuneValues = m_detuneValues.data();
        float* offset_detunes = detuneValues + +quantumFrameOffset;
        m_detune->calculateSampleAccurateValues(r, offset_detunes, nonSilentFramesToProcess);

        // Convert from cents to rate scalar and perform detuning
        float k = 1.f / 1200.f;
        VectorMath::vsmul(offset_detunes, 1, &k, offset_detunes, 1, nonSilentFramesToProcess);
        for (int i = quantumFrameOffset; i < nonSilentFramesToProcess; ++i)
        {
            phaseIncrements[i] *= powf(2, detuneValues[i]);  // FIXME: converting to expf() will be faster.
        }
    }
    else
    {
        // Handle ordinary parameter smoothing/de-zippering if there are no scheduled changes.
        m_detune->smooth(r);
        float detune = m_detune->smoothedValue();
        if (fabsf(detune) > 0.01f)
        {
            float detuneScale = powf(2, detune / 1200);
            for (int i = quantumFrameOffset; i < nonSilentFramesToProcess; ++i)
                phaseIncrements[i] *= detuneScale;
        }
    }

The particular line of this snippet that confuses me is:

        float* offset_detunes = detuneValues + +quantumFrameOffset;

My immediate reaction to this is "there's no way that's valid C++ because ++ only takes one argument and I'm pretty sure the compiler would interpret that as ++". But is this actually valid code? And what would be the (idiomatic) rust equivalent? I get the feeling it might be something like:

let detune_values = self.detune_values.clone();
quantum_frame_offset += 1;
let offset_detunes = detune_values[quantum_frame_offset];

Or something along these lines.

In general, is there a guide that goes over various C++ features and provides idiomatic rust equivalents? (e.g., the library uses inheritance, and though I'd want to use supertraits, I'm pretty sure I won't get the desired results.)

I believe that line is invoking C++'s prefix unary plus operator, not the preincrement operator:

https://en.cppreference.com/w/cpp/language/operator_arithmetic#Unary_arithmetic_operators

The built-in unary plus operator returns the value of its operand. The only situation where it is not a no-op is when the operand has integral type or unscoped enumeration type, which is changed by integral promotion, e.g, it converts char to int or if the operand is subject to lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion.

Of course non-built-in types can override this to mean whatever they want. Assuming that quantumFrameOffset has integral type, an analogous line of Rust would be

let offset_detunes = &detuneValues[quantumFrameOffset.into()..];

Thanks! Now I understand what that was trying to do. I was quite confused.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.